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