Home | History | Annotate | Download | only in source
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*------------------------------------------------------------------------------
     18 
     19     Table of contents
     20 
     21      1. Include headers
     22      2. External compiler flags
     23      3. Module defines
     24      4. Local function prototypes
     25      5. Functions
     26           ComparePictures
     27           h264bsdReorderRefPicList
     28           Mmcop1
     29           Mmcop2
     30           Mmcop3
     31           Mmcop4
     32           Mmcop5
     33           Mmcop6
     34           h264bsdMarkDecRefPic
     35           h264bsdGetRefPicData
     36           h264bsdAllocateDpbImage
     37           SlidingWindowRefPicMarking
     38           h264bsdInitDpb
     39           h264bsdResetDpb
     40           h264bsdInitRefPicList
     41           FindDpbPic
     42           SetPicNums
     43           h264bsdCheckGapsInFrameNum
     44           FindSmallestPicOrderCnt
     45           OutputPicture
     46           h264bsdDpbOutputPicture
     47           h264bsdFlushDpb
     48           h264bsdFreeDpb
     49 
     50 ------------------------------------------------------------------------------*/
     51 
     52 /*------------------------------------------------------------------------------
     53     1. Include headers
     54 ------------------------------------------------------------------------------*/
     55 
     56 #include "h264bsd_cfg.h"
     57 #include "h264bsd_dpb.h"
     58 #include "h264bsd_slice_header.h"
     59 #include "h264bsd_image.h"
     60 #include "h264bsd_util.h"
     61 #include "basetype.h"
     62 
     63 /*------------------------------------------------------------------------------
     64     2. External compiler flags
     65 --------------------------------------------------------------------------------
     66 
     67 --------------------------------------------------------------------------------
     68     3. Module defines
     69 ------------------------------------------------------------------------------*/
     70 
     71 /* macros to determine picture status. Note that IS_SHORT_TERM macro returns
     72  * true also for non-existing pictures because non-existing pictures are
     73  * regarded short term pictures according to H.264 standard */
     74 #define IS_REFERENCE(a) ((a).status)
     75 #define IS_EXISTING(a) ((a).status > NON_EXISTING)
     76 #define IS_SHORT_TERM(a) \
     77     ((a).status == NON_EXISTING || (a).status == SHORT_TERM)
     78 #define IS_LONG_TERM(a) ((a).status == LONG_TERM)
     79 
     80 /* macro to set a picture unused for reference */
     81 #define SET_UNUSED(a) (a).status = UNUSED;
     82 
     83 #define MAX_NUM_REF_IDX_L0_ACTIVE 16
     84 
     85 /*------------------------------------------------------------------------------
     86     4. Local function prototypes
     87 ------------------------------------------------------------------------------*/
     88 
     89 static i32 ComparePictures(const void *ptr1, const void *ptr2);
     90 
     91 static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums);
     92 
     93 static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum);
     94 
     95 static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
     96     u32 longTermFrameIdx);
     97 
     98 static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx);
     99 
    100 static u32 Mmcop5(dpbStorage_t *dpb);
    101 
    102 static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
    103     u32 longTermFrameIdx);
    104 
    105 static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb);
    106 
    107 static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm);
    108 
    109 static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum);
    110 
    111 static dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb);
    112 
    113 static u32 OutputPicture(dpbStorage_t *dpb);
    114 
    115 static void ShellSort(dpbPicture_t *pPic, u32 num);
    116 
    117 /*------------------------------------------------------------------------------
    118 
    119     Function: ComparePictures
    120 
    121         Functional description:
    122             Function to compare dpb pictures, used by the ShellSort() function.
    123             Order of the pictures after sorting shall be as follows:
    124                 1) short term reference pictures starting with the largest
    125                    picNum
    126                 2) long term reference pictures starting with the smallest
    127                    longTermPicNum
    128                 3) pictures unused for reference but needed for display
    129                 4) other pictures
    130 
    131         Returns:
    132             -1      pic 1 is greater than pic 2
    133              0      equal from comparison point of view
    134              1      pic 2 is greater then pic 1
    135 
    136 ------------------------------------------------------------------------------*/
    137 
    138 static i32 ComparePictures(const void *ptr1, const void *ptr2)
    139 {
    140 
    141 /* Variables */
    142 
    143     dpbPicture_t *pic1, *pic2;
    144 
    145 /* Code */
    146 
    147     ASSERT(ptr1);
    148     ASSERT(ptr2);
    149 
    150     pic1 = (dpbPicture_t*)ptr1;
    151     pic2 = (dpbPicture_t*)ptr2;
    152 
    153     /* both are non-reference pictures, check if needed for display */
    154     if (!IS_REFERENCE(*pic1) && !IS_REFERENCE(*pic2))
    155     {
    156         if (pic1->toBeDisplayed && !pic2->toBeDisplayed)
    157             return(-1);
    158         else if (!pic1->toBeDisplayed && pic2->toBeDisplayed)
    159             return(1);
    160         else
    161             return(0);
    162     }
    163     /* only pic 1 needed for reference -> greater */
    164     else if (!IS_REFERENCE(*pic2))
    165         return(-1);
    166     /* only pic 2 needed for reference -> greater */
    167     else if (!IS_REFERENCE(*pic1))
    168         return(1);
    169     /* both are short term reference pictures -> check picNum */
    170     else if (IS_SHORT_TERM(*pic1) && IS_SHORT_TERM(*pic2))
    171     {
    172         if (pic1->picNum > pic2->picNum)
    173             return(-1);
    174         else if (pic1->picNum < pic2->picNum)
    175             return(1);
    176         else
    177             return(0);
    178     }
    179     /* only pic 1 is short term -> greater */
    180     else if (IS_SHORT_TERM(*pic1))
    181         return(-1);
    182     /* only pic 2 is short term -> greater */
    183     else if (IS_SHORT_TERM(*pic2))
    184         return(1);
    185     /* both are long term reference pictures -> check picNum (contains the
    186      * longTermPicNum */
    187     else
    188     {
    189         if (pic1->picNum > pic2->picNum)
    190             return(1);
    191         else if (pic1->picNum < pic2->picNum)
    192             return(-1);
    193         else
    194             return(0);
    195     }
    196 }
    197 
    198 /*------------------------------------------------------------------------------
    199 
    200     Function: h264bsdReorderRefPicList
    201 
    202         Functional description:
    203             Function to perform reference picture list reordering based on
    204             reordering commands received in the slice header. See details
    205             of the process in the H.264 standard.
    206 
    207         Inputs:
    208             dpb             pointer to dpb storage structure
    209             order           pointer to reordering commands
    210             currFrameNum    current frame number
    211             numRefIdxActive number of active reference indices for current
    212                             picture
    213 
    214         Outputs:
    215             dpb             'list' field of the structure reordered
    216 
    217         Returns:
    218             HANTRO_OK      success
    219             HANTRO_NOK     if non-existing pictures referred to in the
    220                            reordering commands
    221 
    222 ------------------------------------------------------------------------------*/
    223 
    224 u32 h264bsdReorderRefPicList(
    225   dpbStorage_t *dpb,
    226   refPicListReordering_t *order,
    227   u32 currFrameNum,
    228   u32 numRefIdxActive)
    229 {
    230 
    231 /* Variables */
    232 
    233     u32 i, j, k, picNumPred, refIdx;
    234     i32 picNum, picNumNoWrap, index;
    235     u32 isShortTerm;
    236 
    237 /* Code */
    238 
    239     ASSERT(order);
    240     ASSERT(currFrameNum <= dpb->maxFrameNum);
    241     ASSERT(numRefIdxActive <= MAX_NUM_REF_IDX_L0_ACTIVE);
    242 
    243     /* set dpb picture numbers for sorting */
    244     SetPicNums(dpb, currFrameNum);
    245 
    246     if (!order->refPicListReorderingFlagL0)
    247         return(HANTRO_OK);
    248 
    249     refIdx     = 0;
    250     picNumPred = currFrameNum;
    251 
    252     i = 0;
    253     while (order->command[i].reorderingOfPicNumsIdc < 3)
    254     {
    255         /* short term */
    256         if (order->command[i].reorderingOfPicNumsIdc < 2)
    257         {
    258             if (order->command[i].reorderingOfPicNumsIdc == 0)
    259             {
    260                 picNumNoWrap =
    261                     (i32)picNumPred - (i32)order->command[i].absDiffPicNum;
    262                 if (picNumNoWrap < 0)
    263                     picNumNoWrap += (i32)dpb->maxFrameNum;
    264             }
    265             else
    266             {
    267                 picNumNoWrap =
    268                     (i32)(picNumPred + order->command[i].absDiffPicNum);
    269                 if (picNumNoWrap >= (i32)dpb->maxFrameNum)
    270                     picNumNoWrap -= (i32)dpb->maxFrameNum;
    271             }
    272             picNumPred = (u32)picNumNoWrap;
    273             picNum = picNumNoWrap;
    274             if ((u32)picNumNoWrap > currFrameNum)
    275                 picNum -= (i32)dpb->maxFrameNum;
    276             isShortTerm = HANTRO_TRUE;
    277         }
    278         /* long term */
    279         else
    280         {
    281             picNum = (i32)order->command[i].longTermPicNum;
    282             isShortTerm = HANTRO_FALSE;
    283 
    284         }
    285         /* find corresponding picture from dpb */
    286         index = FindDpbPic(dpb, picNum, isShortTerm);
    287         if (index < 0 || !IS_EXISTING(dpb->buffer[index]))
    288             return(HANTRO_NOK);
    289 
    290         /* shift pictures */
    291         for (j = numRefIdxActive; j > refIdx; j--)
    292             dpb->list[j] = dpb->list[j-1];
    293         /* put picture into the list */
    294         dpb->list[refIdx++] = &dpb->buffer[index];
    295         /* remove later references to the same picture */
    296         for (j = k = refIdx; j <= numRefIdxActive; j++)
    297             if(dpb->list[j] != &dpb->buffer[index])
    298                 dpb->list[k++] = dpb->list[j];
    299 
    300         i++;
    301     }
    302 
    303     return(HANTRO_OK);
    304 
    305 }
    306 
    307 /*------------------------------------------------------------------------------
    308 
    309     Function: Mmcop1
    310 
    311         Functional description:
    312             Function to mark a short-term reference picture unused for
    313             reference, memory_management_control_operation equal to 1
    314 
    315         Returns:
    316             HANTRO_OK      success
    317             HANTRO_NOK     failure, picture does not exist in the buffer
    318 
    319 ------------------------------------------------------------------------------*/
    320 
    321 static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums)
    322 {
    323 
    324 /* Variables */
    325 
    326     i32 index, picNum;
    327 
    328 /* Code */
    329 
    330     ASSERT(currPicNum < dpb->maxFrameNum);
    331 
    332     picNum = (i32)currPicNum - (i32)differenceOfPicNums;
    333 
    334     index = FindDpbPic(dpb, picNum, HANTRO_TRUE);
    335     if (index < 0)
    336         return(HANTRO_NOK);
    337 
    338     SET_UNUSED(dpb->buffer[index]);
    339     dpb->numRefFrames--;
    340     if (!dpb->buffer[index].toBeDisplayed)
    341         dpb->fullness--;
    342 
    343     return(HANTRO_OK);
    344 
    345 }
    346 
    347 /*------------------------------------------------------------------------------
    348 
    349     Function: Mmcop2
    350 
    351         Functional description:
    352             Function to mark a long-term reference picture unused for
    353             reference, memory_management_control_operation equal to 2
    354 
    355         Returns:
    356             HANTRO_OK      success
    357             HANTRO_NOK     failure, picture does not exist in the buffer
    358 
    359 ------------------------------------------------------------------------------*/
    360 
    361 static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum)
    362 {
    363 
    364 /* Variables */
    365 
    366     i32 index;
    367 
    368 /* Code */
    369 
    370     index = FindDpbPic(dpb, (i32)longTermPicNum, HANTRO_FALSE);
    371     if (index < 0)
    372         return(HANTRO_NOK);
    373 
    374     SET_UNUSED(dpb->buffer[index]);
    375     dpb->numRefFrames--;
    376     if (!dpb->buffer[index].toBeDisplayed)
    377         dpb->fullness--;
    378 
    379     return(HANTRO_OK);
    380 
    381 }
    382 
    383 /*------------------------------------------------------------------------------
    384 
    385     Function: Mmcop3
    386 
    387         Functional description:
    388             Function to assing a longTermFrameIdx to a short-term reference
    389             frame (i.e. to change it to a long-term reference picture),
    390             memory_management_control_operation equal to 3
    391 
    392         Returns:
    393             HANTRO_OK      success
    394             HANTRO_NOK     failure, short-term picture does not exist in the
    395                            buffer or is a non-existing picture, or invalid
    396                            longTermFrameIdx given
    397 
    398 ------------------------------------------------------------------------------*/
    399 
    400 static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
    401     u32 longTermFrameIdx)
    402 {
    403 
    404 /* Variables */
    405 
    406     i32 index, picNum;
    407     u32 i;
    408 
    409 /* Code */
    410 
    411     ASSERT(dpb);
    412     ASSERT(currPicNum < dpb->maxFrameNum);
    413 
    414     if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ||
    415          (longTermFrameIdx > dpb->maxLongTermFrameIdx) )
    416         return(HANTRO_NOK);
    417 
    418     /* check if a long term picture with the same longTermFrameIdx already
    419      * exist and remove it if necessary */
    420     for (i = 0; i < dpb->maxRefFrames; i++)
    421         if (IS_LONG_TERM(dpb->buffer[i]) &&
    422           (u32)dpb->buffer[i].picNum == longTermFrameIdx)
    423         {
    424             SET_UNUSED(dpb->buffer[i]);
    425             dpb->numRefFrames--;
    426             if (!dpb->buffer[i].toBeDisplayed)
    427                 dpb->fullness--;
    428             break;
    429         }
    430 
    431     picNum = (i32)currPicNum - (i32)differenceOfPicNums;
    432 
    433     index = FindDpbPic(dpb, picNum, HANTRO_TRUE);
    434     if (index < 0)
    435         return(HANTRO_NOK);
    436     if (!IS_EXISTING(dpb->buffer[index]))
    437         return(HANTRO_NOK);
    438 
    439     dpb->buffer[index].status = LONG_TERM;
    440     dpb->buffer[index].picNum = (i32)longTermFrameIdx;
    441 
    442     return(HANTRO_OK);
    443 
    444 }
    445 
    446 /*------------------------------------------------------------------------------
    447 
    448     Function: Mmcop4
    449 
    450         Functional description:
    451             Function to set maxLongTermFrameIdx,
    452             memory_management_control_operation equal to 4
    453 
    454         Returns:
    455             HANTRO_OK      success
    456 
    457 ------------------------------------------------------------------------------*/
    458 
    459 static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx)
    460 {
    461 
    462 /* Variables */
    463 
    464     u32 i;
    465 
    466 /* Code */
    467 
    468     dpb->maxLongTermFrameIdx = maxLongTermFrameIdx;
    469 
    470     for (i = 0; i < dpb->maxRefFrames; i++)
    471         if (IS_LONG_TERM(dpb->buffer[i]) &&
    472           ( ((u32)dpb->buffer[i].picNum > maxLongTermFrameIdx) ||
    473             (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ) )
    474         {
    475             SET_UNUSED(dpb->buffer[i]);
    476             dpb->numRefFrames--;
    477             if (!dpb->buffer[i].toBeDisplayed)
    478                 dpb->fullness--;
    479         }
    480 
    481     return(HANTRO_OK);
    482 
    483 }
    484 
    485 /*------------------------------------------------------------------------------
    486 
    487     Function: Mmcop5
    488 
    489         Functional description:
    490             Function to mark all reference pictures unused for reference and
    491             set maxLongTermFrameIdx to NO_LONG_TERM_FRAME_INDICES,
    492             memory_management_control_operation equal to 5. Function flushes
    493             the buffer and places all pictures that are needed for display into
    494             the output buffer.
    495 
    496         Returns:
    497             HANTRO_OK      success
    498 
    499 ------------------------------------------------------------------------------*/
    500 
    501 static u32 Mmcop5(dpbStorage_t *dpb)
    502 {
    503 
    504 /* Variables */
    505 
    506     u32 i;
    507 
    508 /* Code */
    509 
    510     for (i = 0; i < 16; i++)
    511     {
    512         if (IS_REFERENCE(dpb->buffer[i]))
    513         {
    514             SET_UNUSED(dpb->buffer[i]);
    515             if (!dpb->buffer[i].toBeDisplayed)
    516                 dpb->fullness--;
    517         }
    518     }
    519 
    520     /* output all pictures */
    521     while (OutputPicture(dpb) == HANTRO_OK)
    522         ;
    523     dpb->numRefFrames = 0;
    524     dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
    525     dpb->prevRefFrameNum = 0;
    526 
    527     return(HANTRO_OK);
    528 
    529 }
    530 
    531 /*------------------------------------------------------------------------------
    532 
    533     Function: Mmcop6
    534 
    535         Functional description:
    536             Function to assign longTermFrameIdx to the current picture,
    537             memory_management_control_operation equal to 6
    538 
    539         Returns:
    540             HANTRO_OK      success
    541             HANTRO_NOK     invalid longTermFrameIdx or no room for current
    542                            picture in the buffer
    543 
    544 ------------------------------------------------------------------------------*/
    545 
    546 static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
    547     u32 longTermFrameIdx)
    548 {
    549 
    550 /* Variables */
    551 
    552     u32 i;
    553 
    554 /* Code */
    555 
    556     ASSERT(frameNum < dpb->maxFrameNum);
    557 
    558     if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ||
    559          (longTermFrameIdx > dpb->maxLongTermFrameIdx) )
    560         return(HANTRO_NOK);
    561 
    562     /* check if a long term picture with the same longTermFrameIdx already
    563      * exist and remove it if necessary */
    564     for (i = 0; i < dpb->maxRefFrames; i++)
    565         if (IS_LONG_TERM(dpb->buffer[i]) &&
    566           (u32)dpb->buffer[i].picNum == longTermFrameIdx)
    567         {
    568             SET_UNUSED(dpb->buffer[i]);
    569             dpb->numRefFrames--;
    570             if (!dpb->buffer[i].toBeDisplayed)
    571                 dpb->fullness--;
    572             break;
    573         }
    574 
    575     if (dpb->numRefFrames < dpb->maxRefFrames)
    576     {
    577         dpb->currentOut->frameNum = frameNum;
    578         dpb->currentOut->picNum   = (i32)longTermFrameIdx;
    579         dpb->currentOut->picOrderCnt = picOrderCnt;
    580         dpb->currentOut->status   = LONG_TERM;
    581         if (dpb->noReordering)
    582             dpb->currentOut->toBeDisplayed = HANTRO_FALSE;
    583         else
    584             dpb->currentOut->toBeDisplayed = HANTRO_TRUE;
    585         dpb->numRefFrames++;
    586         dpb->fullness++;
    587         return(HANTRO_OK);
    588     }
    589     /* if there is no room, return an error */
    590     else
    591         return(HANTRO_NOK);
    592 
    593 }
    594 
    595 /*------------------------------------------------------------------------------
    596 
    597     Function: h264bsdMarkDecRefPic
    598 
    599         Functional description:
    600             Function to perform reference picture marking process. This
    601             function should be called both for reference and non-reference
    602             pictures.  Non-reference pictures shall have mark pointer set to
    603             NULL.
    604 
    605         Inputs:
    606             dpb         pointer to the DPB data structure
    607             mark        pointer to reference picture marking commands
    608             image       pointer to current picture to be placed in the buffer
    609             frameNum    frame number of the current picture
    610             picOrderCnt picture order count for the current picture
    611             isIdr       flag to indicate if the current picture is an
    612                         IDR picture
    613             currentPicId    identifier for the current picture, from the
    614                             application, stored along with the picture
    615             numErrMbs       number of concealed macroblocks in the current
    616                             picture, stored along with the picture
    617 
    618         Outputs:
    619             dpb         'buffer' modified, possible output frames placed into
    620                         'outBuf'
    621 
    622         Returns:
    623             HANTRO_OK   success
    624             HANTRO_NOK  failure
    625 
    626 ------------------------------------------------------------------------------*/
    627 
    628 u32 h264bsdMarkDecRefPic(
    629   dpbStorage_t *dpb,
    630   decRefPicMarking_t *mark,
    631   image_t *image,
    632   u32 frameNum,
    633   i32 picOrderCnt,
    634   u32 isIdr,
    635   u32 currentPicId,
    636   u32 numErrMbs)
    637 {
    638 
    639 /* Variables */
    640 
    641     u32 i, status;
    642     u32 markedAsLongTerm;
    643     u32 toBeDisplayed;
    644 
    645 /* Code */
    646 
    647     ASSERT(dpb);
    648     ASSERT(mark || !isIdr);
    649     ASSERT(!isIdr || (frameNum == 0 && picOrderCnt == 0));
    650     ASSERT(frameNum < dpb->maxFrameNum);
    651 
    652     if (image->data != dpb->currentOut->data)
    653     {
    654         EPRINT("TRYING TO MARK NON-ALLOCATED IMAGE");
    655         return(HANTRO_NOK);
    656     }
    657 
    658     dpb->lastContainsMmco5 = HANTRO_FALSE;
    659     status = HANTRO_OK;
    660 
    661     toBeDisplayed = dpb->noReordering ? HANTRO_FALSE : HANTRO_TRUE;
    662 
    663     /* non-reference picture, stored for display reordering purposes */
    664     if (mark == NULL)
    665     {
    666         dpb->currentOut->status = UNUSED;
    667         dpb->currentOut->frameNum = frameNum;
    668         dpb->currentOut->picNum = (i32)frameNum;
    669         dpb->currentOut->picOrderCnt = picOrderCnt;
    670         dpb->currentOut->toBeDisplayed = toBeDisplayed;
    671         if (!dpb->noReordering)
    672             dpb->fullness++;
    673     }
    674     /* IDR picture */
    675     else if (isIdr)
    676     {
    677 
    678         /* h264bsdCheckGapsInFrameNum not called for IDR pictures -> have to
    679          * reset numOut and outIndex here */
    680         dpb->numOut = dpb->outIndex = 0;
    681 
    682         /* flush the buffer */
    683         Mmcop5(dpb);
    684         /* if noOutputOfPriorPicsFlag was set -> the pictures preceding the
    685          * IDR picture shall not be output -> set output buffer empty */
    686         if (mark->noOutputOfPriorPicsFlag || dpb->noReordering)
    687         {
    688             dpb->numOut = 0;
    689             dpb->outIndex = 0;
    690         }
    691 
    692         if (mark->longTermReferenceFlag)
    693         {
    694             dpb->currentOut->status = LONG_TERM;
    695             dpb->maxLongTermFrameIdx = 0;
    696         }
    697         else
    698         {
    699             dpb->currentOut->status = SHORT_TERM;
    700             dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
    701         }
    702         dpb->currentOut->frameNum  = 0;
    703         dpb->currentOut->picNum    = 0;
    704         dpb->currentOut->picOrderCnt = 0;
    705         dpb->currentOut->toBeDisplayed = toBeDisplayed;
    706         dpb->fullness = 1;
    707         dpb->numRefFrames = 1;
    708     }
    709     /* reference picture */
    710     else
    711     {
    712         markedAsLongTerm = HANTRO_FALSE;
    713         if (mark->adaptiveRefPicMarkingModeFlag)
    714         {
    715             i = 0;
    716             while (mark->operation[i].memoryManagementControlOperation)
    717             {
    718                 switch (mark->operation[i].memoryManagementControlOperation)
    719                 {
    720                     case 1:
    721                         status = Mmcop1(
    722                           dpb,
    723                           frameNum,
    724                           mark->operation[i].differenceOfPicNums);
    725                         break;
    726 
    727                     case 2:
    728                         status = Mmcop2(dpb, mark->operation[i].longTermPicNum);
    729                         break;
    730 
    731                     case 3:
    732                         status =  Mmcop3(
    733                           dpb,
    734                           frameNum,
    735                           mark->operation[i].differenceOfPicNums,
    736                           mark->operation[i].longTermFrameIdx);
    737                         break;
    738 
    739                     case 4:
    740                         status = Mmcop4(
    741                           dpb,
    742                           mark->operation[i].maxLongTermFrameIdx);
    743                         break;
    744 
    745                     case 5:
    746                         status = Mmcop5(dpb);
    747                         dpb->lastContainsMmco5 = HANTRO_TRUE;
    748                         frameNum = 0;
    749                         break;
    750 
    751                     case 6:
    752                         status = Mmcop6(
    753                           dpb,
    754                           frameNum,
    755                           picOrderCnt,
    756                           mark->operation[i].longTermFrameIdx);
    757                         if (status == HANTRO_OK)
    758                             markedAsLongTerm = HANTRO_TRUE;
    759                         break;
    760 
    761                     default: /* invalid memory management control operation */
    762                         status = HANTRO_NOK;
    763                         break;
    764                 }
    765                 if (status != HANTRO_OK)
    766                 {
    767                     break;
    768                 }
    769                 i++;
    770             }
    771         }
    772         else
    773         {
    774             status = SlidingWindowRefPicMarking(dpb);
    775         }
    776         /* if current picture was not marked as long-term reference by
    777          * memory management control operation 6 -> mark current as short
    778          * term and insert it into dpb (if there is room) */
    779         if (!markedAsLongTerm)
    780         {
    781             if (dpb->numRefFrames < dpb->maxRefFrames)
    782             {
    783                 dpb->currentOut->frameNum = frameNum;
    784                 dpb->currentOut->picNum   = (i32)frameNum;
    785                 dpb->currentOut->picOrderCnt = picOrderCnt;
    786                 dpb->currentOut->status   = SHORT_TERM;
    787                 dpb->currentOut->toBeDisplayed = toBeDisplayed;
    788                 dpb->fullness++;
    789                 dpb->numRefFrames++;
    790             }
    791             /* no room */
    792             else
    793             {
    794                 status = HANTRO_NOK;
    795             }
    796         }
    797     }
    798 
    799     dpb->currentOut->isIdr = isIdr;
    800     dpb->currentOut->picId = currentPicId;
    801     dpb->currentOut->numErrMbs = numErrMbs;
    802 
    803     /* dpb was initialized to not to reorder the pictures -> output current
    804      * picture immediately */
    805     if (dpb->noReordering)
    806     {
    807         ASSERT(dpb->numOut == 0);
    808         ASSERT(dpb->outIndex == 0);
    809         dpb->outBuf[dpb->numOut].data  = dpb->currentOut->data;
    810         dpb->outBuf[dpb->numOut].isIdr = dpb->currentOut->isIdr;
    811         dpb->outBuf[dpb->numOut].picId = dpb->currentOut->picId;
    812         dpb->outBuf[dpb->numOut].numErrMbs = dpb->currentOut->numErrMbs;
    813         dpb->numOut++;
    814     }
    815     else
    816     {
    817         /* output pictures if buffer full */
    818         while (dpb->fullness > dpb->dpbSize)
    819         {
    820             i = OutputPicture(dpb);
    821             ASSERT(i == HANTRO_OK);
    822         }
    823     }
    824 
    825     /* sort dpb */
    826     ShellSort(dpb->buffer, dpb->dpbSize+1);
    827 
    828     return(status);
    829 
    830 }
    831 
    832 /*------------------------------------------------------------------------------
    833 
    834     Function: h264bsdGetRefPicData
    835 
    836         Functional description:
    837             Function to get reference picture data from the reference picture
    838             list
    839 
    840         Returns:
    841             pointer to desired reference picture data
    842             NULL if invalid index or non-existing picture referred
    843 
    844 ------------------------------------------------------------------------------*/
    845 
    846 u8* h264bsdGetRefPicData(dpbStorage_t *dpb, u32 index)
    847 {
    848 
    849 /* Variables */
    850 
    851 /* Code */
    852 
    853     if(index > 16 || dpb->list[index] == NULL)
    854         return(NULL);
    855     else if(!IS_EXISTING(*dpb->list[index]))
    856         return(NULL);
    857     else
    858         return(dpb->list[index]->data);
    859 
    860 }
    861 
    862 /*------------------------------------------------------------------------------
    863 
    864     Function: h264bsdAllocateDpbImage
    865 
    866         Functional description:
    867             function to allocate memory for a image. This function does not
    868             really allocate any memory but reserves one of the buffer
    869             positions for decoding of current picture
    870 
    871         Returns:
    872             pointer to memory area for the image
    873 
    874 
    875 ------------------------------------------------------------------------------*/
    876 
    877 u8* h264bsdAllocateDpbImage(dpbStorage_t *dpb)
    878 {
    879 
    880 /* Variables */
    881 
    882 /* Code */
    883 
    884     ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed &&
    885             !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) );
    886     ASSERT(dpb->fullness <=  dpb->dpbSize);
    887 
    888     dpb->currentOut = dpb->buffer + dpb->dpbSize;
    889 
    890     return(dpb->currentOut->data);
    891 
    892 }
    893 
    894 /*------------------------------------------------------------------------------
    895 
    896     Function: SlidingWindowRefPicMarking
    897 
    898         Functional description:
    899             Function to perform sliding window refence picture marking process.
    900 
    901         Outputs:
    902             HANTRO_OK      success
    903             HANTRO_NOK     failure, no short-term reference frame found that
    904                            could be marked unused
    905 
    906 
    907 ------------------------------------------------------------------------------*/
    908 
    909 static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb)
    910 {
    911 
    912 /* Variables */
    913 
    914     i32 index, picNum;
    915     u32 i;
    916 
    917 /* Code */
    918 
    919     if (dpb->numRefFrames < dpb->maxRefFrames)
    920     {
    921         return(HANTRO_OK);
    922     }
    923     else
    924     {
    925         index = -1;
    926         picNum = 0;
    927         /* find the oldest short term picture */
    928         for (i = 0; i < dpb->numRefFrames; i++)
    929             if (IS_SHORT_TERM(dpb->buffer[i]))
    930                 if (dpb->buffer[i].picNum < picNum || index == -1)
    931                 {
    932                     index = (i32)i;
    933                     picNum = dpb->buffer[i].picNum;
    934                 }
    935         if (index >= 0)
    936         {
    937             SET_UNUSED(dpb->buffer[index]);
    938             dpb->numRefFrames--;
    939             if (!dpb->buffer[index].toBeDisplayed)
    940                 dpb->fullness--;
    941 
    942             return(HANTRO_OK);
    943         }
    944     }
    945 
    946     return(HANTRO_NOK);
    947 
    948 }
    949 
    950 /*------------------------------------------------------------------------------
    951 
    952     Function: h264bsdInitDpb
    953 
    954         Functional description:
    955             Function to initialize DPB. Reserves memories for the buffer,
    956             reference picture list and output buffer. dpbSize indicates
    957             the maximum DPB size indicated by the levelIdc in the stream.
    958             If noReordering flag is FALSE the DPB stores dpbSize pictures
    959             for display reordering purposes. On the other hand, if the
    960             flag is TRUE the DPB only stores maxRefFrames reference pictures
    961             and outputs all the pictures immediately.
    962 
    963         Inputs:
    964             picSizeInMbs    picture size in macroblocks
    965             dpbSize         size of the DPB (number of pictures)
    966             maxRefFrames    max number of reference frames
    967             maxFrameNum     max frame number
    968             noReordering    flag to indicate that DPB does not have to
    969                             prepare to reorder frames for display
    970 
    971         Outputs:
    972             dpb             pointer to dpb data storage
    973 
    974         Returns:
    975             HANTRO_OK       success
    976             MEMORY_ALLOCATION_ERROR if memory allocation failed
    977 
    978 ------------------------------------------------------------------------------*/
    979 
    980 u32 h264bsdInitDpb(
    981   dpbStorage_t *dpb,
    982   u32 picSizeInMbs,
    983   u32 dpbSize,
    984   u32 maxRefFrames,
    985   u32 maxFrameNum,
    986   u32 noReordering)
    987 {
    988 
    989 /* Variables */
    990 
    991     u32 i;
    992 
    993 /* Code */
    994 
    995     ASSERT(picSizeInMbs);
    996     ASSERT(maxRefFrames <= MAX_NUM_REF_PICS);
    997     ASSERT(maxRefFrames <= dpbSize);
    998     ASSERT(maxFrameNum);
    999     ASSERT(dpbSize);
   1000 
   1001     dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
   1002     dpb->maxRefFrames        = MAX(maxRefFrames, 1);
   1003     if (noReordering)
   1004         dpb->dpbSize         = dpb->maxRefFrames;
   1005     else
   1006         dpb->dpbSize         = dpbSize;
   1007     dpb->maxFrameNum         = maxFrameNum;
   1008     dpb->noReordering        = noReordering;
   1009     dpb->fullness            = 0;
   1010     dpb->numRefFrames        = 0;
   1011     dpb->prevRefFrameNum     = 0;
   1012 
   1013     ALLOCATE(dpb->buffer, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t);
   1014     if (dpb->buffer == NULL)
   1015         return(MEMORY_ALLOCATION_ERROR);
   1016     H264SwDecMemset(dpb->buffer, 0,
   1017             (MAX_NUM_REF_IDX_L0_ACTIVE + 1)*sizeof(dpbPicture_t));
   1018     for (i = 0; i < dpb->dpbSize + 1; i++)
   1019     {
   1020         /* Allocate needed amount of memory, which is:
   1021          * image size + 32 + 15, where 32 cames from the fact that in ARM OpenMax
   1022          * DL implementation Functions may read beyond the end of an array,
   1023          * by a maximum of 32 bytes. And +15 cames for the need to align memory
   1024          * to 16-byte boundary */
   1025         ALLOCATE(dpb->buffer[i].pAllocatedData, (picSizeInMbs*384 + 32+15), u8);
   1026         if (dpb->buffer[i].pAllocatedData == NULL)
   1027             return(MEMORY_ALLOCATION_ERROR);
   1028 
   1029         dpb->buffer[i].data = ALIGN(dpb->buffer[i].pAllocatedData, 16);
   1030     }
   1031 
   1032     ALLOCATE(dpb->list, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t*);
   1033     ALLOCATE(dpb->outBuf, dpb->dpbSize+1, dpbOutPicture_t);
   1034 
   1035     if (dpb->list == NULL || dpb->outBuf == NULL)
   1036         return(MEMORY_ALLOCATION_ERROR);
   1037 
   1038     H264SwDecMemset(dpb->list, 0,
   1039             ((MAX_NUM_REF_IDX_L0_ACTIVE + 1) * sizeof(dpbPicture_t*)) );
   1040 
   1041     dpb->numOut = dpb->outIndex = 0;
   1042 
   1043     return(HANTRO_OK);
   1044 
   1045 }
   1046 
   1047 /*------------------------------------------------------------------------------
   1048 
   1049     Function: h264bsdResetDpb
   1050 
   1051         Functional description:
   1052             Function to reset DPB. This function should be called when an IDR
   1053             slice (other than the first) activates new sequence parameter set.
   1054             Function calls h264bsdFreeDpb to free old allocated memories and
   1055             h264bsdInitDpb to re-initialize the DPB. Same inputs, outputs and
   1056             returns as for h264bsdInitDpb.
   1057 
   1058 ------------------------------------------------------------------------------*/
   1059 
   1060 u32 h264bsdResetDpb(
   1061   dpbStorage_t *dpb,
   1062   u32 picSizeInMbs,
   1063   u32 dpbSize,
   1064   u32 maxRefFrames,
   1065   u32 maxFrameNum,
   1066   u32 noReordering)
   1067 {
   1068 
   1069 /* Code */
   1070 
   1071     ASSERT(picSizeInMbs);
   1072     ASSERT(maxRefFrames <= MAX_NUM_REF_PICS);
   1073     ASSERT(maxRefFrames <= dpbSize);
   1074     ASSERT(maxFrameNum);
   1075     ASSERT(dpbSize);
   1076 
   1077     h264bsdFreeDpb(dpb);
   1078 
   1079     return h264bsdInitDpb(dpb, picSizeInMbs, dpbSize, maxRefFrames,
   1080                           maxFrameNum, noReordering);
   1081 }
   1082 
   1083 /*------------------------------------------------------------------------------
   1084 
   1085     Function: h264bsdInitRefPicList
   1086 
   1087         Functional description:
   1088             Function to initialize reference picture list. Function just
   1089             sets pointers in the list according to pictures in the buffer.
   1090             The buffer is assumed to contain pictures sorted according to
   1091             what the H.264 standard says about initial reference picture list.
   1092 
   1093         Inputs:
   1094             dpb     pointer to dpb data structure
   1095 
   1096         Outputs:
   1097             dpb     'list' field initialized
   1098 
   1099         Returns:
   1100             none
   1101 
   1102 ------------------------------------------------------------------------------*/
   1103 
   1104 void h264bsdInitRefPicList(dpbStorage_t *dpb)
   1105 {
   1106 
   1107 /* Variables */
   1108 
   1109     u32 i;
   1110 
   1111 /* Code */
   1112 
   1113     for (i = 0; i < dpb->numRefFrames; i++)
   1114         dpb->list[i] = &dpb->buffer[i];
   1115 
   1116 }
   1117 
   1118 /*------------------------------------------------------------------------------
   1119 
   1120     Function: FindDpbPic
   1121 
   1122         Functional description:
   1123             Function to find a reference picture from the buffer. The picture
   1124             to be found is identified by picNum and isShortTerm flag.
   1125 
   1126         Returns:
   1127             index of the picture in the buffer
   1128             -1 if the specified picture was not found in the buffer
   1129 
   1130 ------------------------------------------------------------------------------*/
   1131 
   1132 static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm)
   1133 {
   1134 
   1135 /* Variables */
   1136 
   1137     u32 i = 0;
   1138     u32 found = HANTRO_FALSE;
   1139 
   1140 /* Code */
   1141 
   1142     if (isShortTerm)
   1143     {
   1144         while (i < dpb->maxRefFrames && !found)
   1145         {
   1146             if (IS_SHORT_TERM(dpb->buffer[i]) &&
   1147               dpb->buffer[i].picNum == picNum)
   1148                 found = HANTRO_TRUE;
   1149             else
   1150                 i++;
   1151         }
   1152     }
   1153     else
   1154     {
   1155         ASSERT(picNum >= 0);
   1156         while (i < dpb->maxRefFrames && !found)
   1157         {
   1158             if (IS_LONG_TERM(dpb->buffer[i]) &&
   1159               dpb->buffer[i].picNum == picNum)
   1160                 found = HANTRO_TRUE;
   1161             else
   1162                 i++;
   1163         }
   1164     }
   1165 
   1166     if (found)
   1167         return((i32)i);
   1168     else
   1169         return(-1);
   1170 
   1171 }
   1172 
   1173 /*------------------------------------------------------------------------------
   1174 
   1175     Function: SetPicNums
   1176 
   1177         Functional description:
   1178             Function to set picNum values for short-term pictures in the
   1179             buffer. Numbering of pictures is based on frame numbers and as
   1180             frame numbers are modulo maxFrameNum -> frame numbers of older
   1181             pictures in the buffer may be bigger than the currFrameNum.
   1182             picNums will be set so that current frame has the largest picNum
   1183             and all the short-term frames in the buffer will get smaller picNum
   1184             representing their "distance" from the current frame. This
   1185             function kind of maps the modulo arithmetic back to normal.
   1186 
   1187 ------------------------------------------------------------------------------*/
   1188 
   1189 static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum)
   1190 {
   1191 
   1192 /* Variables */
   1193 
   1194     u32 i;
   1195     i32 frameNumWrap;
   1196 
   1197 /* Code */
   1198 
   1199     ASSERT(dpb);
   1200     ASSERT(currFrameNum < dpb->maxFrameNum);
   1201 
   1202     for (i = 0; i < dpb->numRefFrames; i++)
   1203         if (IS_SHORT_TERM(dpb->buffer[i]))
   1204         {
   1205             if (dpb->buffer[i].frameNum > currFrameNum)
   1206                 frameNumWrap =
   1207                     (i32)dpb->buffer[i].frameNum - (i32)dpb->maxFrameNum;
   1208             else
   1209                 frameNumWrap = (i32)dpb->buffer[i].frameNum;
   1210             dpb->buffer[i].picNum = frameNumWrap;
   1211         }
   1212 
   1213 }
   1214 
   1215 /*------------------------------------------------------------------------------
   1216 
   1217     Function: h264bsdCheckGapsInFrameNum
   1218 
   1219         Functional description:
   1220             Function to check gaps in frame_num and generate non-existing
   1221             (short term) reference pictures if necessary. This function should
   1222             be called only for non-IDR pictures.
   1223 
   1224         Inputs:
   1225             dpb         pointer to dpb data structure
   1226             frameNum    frame number of the current picture
   1227             isRefPic    flag to indicate if current picture is a reference or
   1228                         non-reference picture
   1229             gapsAllowed Flag which indicates active SPS stance on whether
   1230                         to allow gaps
   1231 
   1232         Outputs:
   1233             dpb         'buffer' possibly modified by inserting non-existing
   1234                         pictures with sliding window marking process
   1235 
   1236         Returns:
   1237             HANTRO_OK   success
   1238             HANTRO_NOK  error in sliding window reference picture marking or
   1239                         frameNum equal to previous reference frame used for
   1240                         a reference picture
   1241 
   1242 ------------------------------------------------------------------------------*/
   1243 
   1244 u32 h264bsdCheckGapsInFrameNum(dpbStorage_t *dpb, u32 frameNum, u32 isRefPic,
   1245                                u32 gapsAllowed)
   1246 {
   1247 
   1248 /* Variables */
   1249 
   1250     u32 unUsedShortTermFrameNum;
   1251     u8 *tmp;
   1252 
   1253 /* Code */
   1254 
   1255     ASSERT(dpb);
   1256     ASSERT(dpb->fullness <= dpb->dpbSize);
   1257     ASSERT(frameNum < dpb->maxFrameNum);
   1258 
   1259     dpb->numOut = 0;
   1260     dpb->outIndex = 0;
   1261 
   1262     if(!gapsAllowed)
   1263         return(HANTRO_OK);
   1264 
   1265     if ( (frameNum != dpb->prevRefFrameNum) &&
   1266          (frameNum != ((dpb->prevRefFrameNum + 1) % dpb->maxFrameNum)))
   1267     {
   1268 
   1269         unUsedShortTermFrameNum = (dpb->prevRefFrameNum + 1) % dpb->maxFrameNum;
   1270 
   1271         /* store data pointer of last buffer position to be used as next
   1272          * "allocated" data pointer if last buffer position after this process
   1273          * contains data pointer located in outBuf (buffer placed in the output
   1274          * shall not be overwritten by the current picture) */
   1275         tmp = dpb->buffer[dpb->dpbSize].data;
   1276         do
   1277         {
   1278             SetPicNums(dpb, unUsedShortTermFrameNum);
   1279 
   1280             if (SlidingWindowRefPicMarking(dpb) != HANTRO_OK)
   1281             {
   1282                 return(HANTRO_NOK);
   1283             }
   1284 
   1285             /* output pictures if buffer full */
   1286             while (dpb->fullness >= dpb->dpbSize)
   1287             {
   1288 #ifdef _ASSERT_USED
   1289                 ASSERT(!dpb->noReordering);
   1290                 ASSERT(OutputPicture(dpb) == HANTRO_OK);
   1291 #else
   1292                 OutputPicture(dpb);
   1293 #endif
   1294             }
   1295 
   1296             /* add to end of list */
   1297             ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed &&
   1298                     !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) );
   1299             dpb->buffer[dpb->dpbSize].status = NON_EXISTING;
   1300             dpb->buffer[dpb->dpbSize].frameNum = unUsedShortTermFrameNum;
   1301             dpb->buffer[dpb->dpbSize].picNum   = (i32)unUsedShortTermFrameNum;
   1302             dpb->buffer[dpb->dpbSize].picOrderCnt = 0;
   1303             dpb->buffer[dpb->dpbSize].toBeDisplayed = HANTRO_FALSE;
   1304             dpb->fullness++;
   1305             dpb->numRefFrames++;
   1306 
   1307             /* sort the buffer */
   1308             ShellSort(dpb->buffer, dpb->dpbSize+1);
   1309 
   1310             unUsedShortTermFrameNum = (unUsedShortTermFrameNum + 1) %
   1311                 dpb->maxFrameNum;
   1312 
   1313         } while (unUsedShortTermFrameNum != frameNum);
   1314 
   1315         /* pictures placed in output buffer -> check that 'data' in
   1316          * buffer position dpbSize is not in the output buffer (this will be
   1317          * "allocated" by h264bsdAllocateDpbImage). If it is -> exchange data
   1318          * pointer with the one stored in the beginning */
   1319         if (dpb->numOut)
   1320         {
   1321             u32 i;
   1322 
   1323             for (i = 0; i < dpb->numOut; i++)
   1324             {
   1325                 if (dpb->outBuf[i].data == dpb->buffer[dpb->dpbSize].data)
   1326                 {
   1327                     /* find buffer position containing data pointer stored in
   1328                      * tmp */
   1329                     for (i = 0; i < dpb->dpbSize; i++)
   1330                     {
   1331                         if (dpb->buffer[i].data == tmp)
   1332                         {
   1333                             dpb->buffer[i].data =
   1334                                 dpb->buffer[dpb->dpbSize].data;
   1335                             dpb->buffer[dpb->dpbSize].data = tmp;
   1336                             break;
   1337                         }
   1338                     }
   1339                     ASSERT(i < dpb->dpbSize);
   1340                     break;
   1341                 }
   1342             }
   1343         }
   1344     }
   1345     /* frameNum for reference pictures shall not be the same as for previous
   1346      * reference picture, otherwise accesses to pictures in the buffer cannot
   1347      * be solved unambiguously */
   1348     else if (isRefPic && frameNum == dpb->prevRefFrameNum)
   1349     {
   1350         return(HANTRO_NOK);
   1351     }
   1352 
   1353     /* save current frame_num in prevRefFrameNum. For non-reference frame
   1354      * prevFrameNum is set to frame number of last non-existing frame above */
   1355     if (isRefPic)
   1356         dpb->prevRefFrameNum = frameNum;
   1357     else if (frameNum != dpb->prevRefFrameNum)
   1358     {
   1359         dpb->prevRefFrameNum =
   1360             (frameNum + dpb->maxFrameNum - 1) % dpb->maxFrameNum;
   1361     }
   1362 
   1363     return(HANTRO_OK);
   1364 
   1365 }
   1366 
   1367 /*------------------------------------------------------------------------------
   1368 
   1369     Function: FindSmallestPicOrderCnt
   1370 
   1371         Functional description:
   1372             Function to find picture with smallest picture order count. This
   1373             will be the next picture in display order.
   1374 
   1375         Returns:
   1376             pointer to the picture, NULL if no pictures to be displayed
   1377 
   1378 ------------------------------------------------------------------------------*/
   1379 
   1380 dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb)
   1381 {
   1382 
   1383 /* Variables */
   1384 
   1385     u32 i;
   1386     i32 picOrderCnt;
   1387     dpbPicture_t *tmp;
   1388 
   1389 /* Code */
   1390 
   1391     ASSERT(dpb);
   1392 
   1393     picOrderCnt = 0x7FFFFFFF;
   1394     tmp = NULL;
   1395 
   1396     for (i = 0; i <= dpb->dpbSize; i++)
   1397     {
   1398         if (dpb->buffer[i].toBeDisplayed &&
   1399             (dpb->buffer[i].picOrderCnt < picOrderCnt))
   1400         {
   1401             tmp = dpb->buffer + i;
   1402             picOrderCnt = dpb->buffer[i].picOrderCnt;
   1403         }
   1404     }
   1405 
   1406     return(tmp);
   1407 
   1408 }
   1409 
   1410 /*------------------------------------------------------------------------------
   1411 
   1412     Function: OutputPicture
   1413 
   1414         Functional description:
   1415             Function to put next display order picture into the output buffer.
   1416 
   1417         Returns:
   1418             HANTRO_OK      success
   1419             HANTRO_NOK     no pictures to display
   1420 
   1421 ------------------------------------------------------------------------------*/
   1422 
   1423 u32 OutputPicture(dpbStorage_t *dpb)
   1424 {
   1425 
   1426 /* Variables */
   1427 
   1428     dpbPicture_t *tmp;
   1429 
   1430 /* Code */
   1431 
   1432     ASSERT(dpb);
   1433 
   1434     if (dpb->noReordering)
   1435         return(HANTRO_NOK);
   1436 
   1437     tmp = FindSmallestPicOrderCnt(dpb);
   1438 
   1439     /* no pictures to be displayed */
   1440     if (tmp == NULL)
   1441         return(HANTRO_NOK);
   1442 
   1443     dpb->outBuf[dpb->numOut].data  = tmp->data;
   1444     dpb->outBuf[dpb->numOut].isIdr = tmp->isIdr;
   1445     dpb->outBuf[dpb->numOut].picId = tmp->picId;
   1446     dpb->outBuf[dpb->numOut].numErrMbs = tmp->numErrMbs;
   1447     dpb->numOut++;
   1448 
   1449     tmp->toBeDisplayed = HANTRO_FALSE;
   1450     if (!IS_REFERENCE(*tmp))
   1451     {
   1452         dpb->fullness--;
   1453     }
   1454 
   1455     return(HANTRO_OK);
   1456 
   1457 }
   1458 
   1459 /*------------------------------------------------------------------------------
   1460 
   1461     Function: h264bsdDpbOutputPicture
   1462 
   1463         Functional description:
   1464             Function to get next display order picture from the output buffer.
   1465 
   1466         Return:
   1467             pointer to output picture structure, NULL if no pictures to
   1468             display
   1469 
   1470 ------------------------------------------------------------------------------*/
   1471 
   1472 dpbOutPicture_t* h264bsdDpbOutputPicture(dpbStorage_t *dpb)
   1473 {
   1474 
   1475 /* Variables */
   1476 
   1477 /* Code */
   1478 
   1479     ASSERT(dpb);
   1480 
   1481     if (dpb->outIndex < dpb->numOut)
   1482         return(dpb->outBuf + dpb->outIndex++);
   1483     else
   1484         return(NULL);
   1485 
   1486 }
   1487 
   1488 /*------------------------------------------------------------------------------
   1489 
   1490     Function: h264bsdFlushDpb
   1491 
   1492         Functional description:
   1493             Function to flush the DPB. Function puts all pictures needed for
   1494             display into the output buffer. This function shall be called in
   1495             the end of the stream to obtain pictures buffered for display
   1496             re-ordering purposes.
   1497 
   1498 ------------------------------------------------------------------------------*/
   1499 
   1500 void h264bsdFlushDpb(dpbStorage_t *dpb)
   1501 {
   1502 
   1503     /* don't do anything if buffer not reserved */
   1504     if (dpb->buffer)
   1505     {
   1506         dpb->flushed = 1;
   1507         /* output all pictures */
   1508         while (OutputPicture(dpb) == HANTRO_OK)
   1509             ;
   1510     }
   1511 
   1512 }
   1513 
   1514 /*------------------------------------------------------------------------------
   1515 
   1516     Function: h264bsdFreeDpb
   1517 
   1518         Functional description:
   1519             Function to free memories reserved for the DPB.
   1520 
   1521 ------------------------------------------------------------------------------*/
   1522 
   1523 void h264bsdFreeDpb(dpbStorage_t *dpb)
   1524 {
   1525 
   1526 /* Variables */
   1527 
   1528     u32 i;
   1529 
   1530 /* Code */
   1531 
   1532     ASSERT(dpb);
   1533 
   1534     if (dpb->buffer)
   1535     {
   1536         for (i = 0; i < dpb->dpbSize+1; i++)
   1537         {
   1538             FREE(dpb->buffer[i].pAllocatedData);
   1539         }
   1540     }
   1541     FREE(dpb->buffer);
   1542     FREE(dpb->list);
   1543     FREE(dpb->outBuf);
   1544 
   1545 }
   1546 
   1547 /*------------------------------------------------------------------------------
   1548 
   1549     Function: ShellSort
   1550 
   1551         Functional description:
   1552             Sort pictures in the buffer. Function implements Shell's method,
   1553             i.e. diminishing increment sort. See e.g. "Numerical Recipes in C"
   1554             for more information.
   1555 
   1556 ------------------------------------------------------------------------------*/
   1557 
   1558 static void ShellSort(dpbPicture_t *pPic, u32 num)
   1559 {
   1560 
   1561     u32 i, j;
   1562     u32 step;
   1563     dpbPicture_t tmpPic;
   1564 
   1565     step = 7;
   1566 
   1567     while (step)
   1568     {
   1569         for (i = step; i < num; i++)
   1570         {
   1571             tmpPic = pPic[i];
   1572             j = i;
   1573             while (j >= step && ComparePictures(pPic + j - step, &tmpPic) > 0)
   1574             {
   1575                 pPic[j] = pPic[j-step];
   1576                 j -= step;
   1577             }
   1578             pPic[j] = tmpPic;
   1579         }
   1580         step >>= 1;
   1581     }
   1582 
   1583 }
   1584 
   1585