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           h264bsdDecodePicOrderCnt
     27 
     28 ------------------------------------------------------------------------------*/
     29 
     30 /*------------------------------------------------------------------------------
     31     1. Include headers
     32 ------------------------------------------------------------------------------*/
     33 
     34 #include "h264bsd_util.h"
     35 #include "h264bsd_pic_order_cnt.h"
     36 
     37 /*------------------------------------------------------------------------------
     38     2. External compiler flags
     39 --------------------------------------------------------------------------------
     40 
     41 --------------------------------------------------------------------------------
     42     3. Module defines
     43 ------------------------------------------------------------------------------*/
     44 
     45 /*------------------------------------------------------------------------------
     46     4. Local function prototypes
     47 ------------------------------------------------------------------------------*/
     48 
     49 /*------------------------------------------------------------------------------
     50 
     51     Function: h264bsdDecodePicOrderCnt
     52 
     53         Functional description:
     54             Compute picture order count for a picture. Function implements
     55             computation of all POC types (0, 1 and 2), type is obtained from
     56             sps. See standard for description of the POC types and how POC is
     57             computed for each type.
     58 
     59             Function returns the minimum of top field and bottom field pic
     60             order counts.
     61 
     62         Inputs:
     63             poc         pointer to previous results
     64             sps         pointer to sequence parameter set
     65             slicHeader  pointer to current slice header, frame number and
     66                         other params needed for POC computation
     67             pNalUnit    pointer to current NAL unit structrue, function needs
     68                         to know if this is an IDR picture and also if this is
     69                         a reference picture
     70 
     71         Outputs:
     72             poc         results stored here for computation of next POC
     73 
     74         Returns:
     75             picture order count
     76 
     77 ------------------------------------------------------------------------------*/
     78 
     79 i32 h264bsdDecodePicOrderCnt(pocStorage_t *poc, seqParamSet_t *sps,
     80     sliceHeader_t *pSliceHeader, nalUnit_t *pNalUnit)
     81 {
     82 
     83 /* Variables */
     84 
     85     u32 i;
     86     i32 picOrderCnt;
     87     u32 frameNumOffset, absFrameNum, picOrderCntCycleCnt;
     88     u32 frameNumInPicOrderCntCycle;
     89     i32 expectedDeltaPicOrderCntCycle;
     90     u32 containsMmco5;
     91 
     92 /* Code */
     93 
     94     ASSERT(poc);
     95     ASSERT(sps);
     96     ASSERT(pSliceHeader);
     97     ASSERT(pNalUnit);
     98     ASSERT(sps->picOrderCntType <= 2);
     99 
    100 #if 0
    101     /* JanSa: I don't think this is necessary, don't see any reason to
    102      * increment prevFrameNum one by one instead of one big increment.
    103      * However, standard specifies that this should be done -> if someone
    104      * figures out any case when the outcome would be different for step by
    105      * step increment, this part of the code should be enabled */
    106 
    107     /* if there was a gap in frame numbering and picOrderCntType is 1 or 2 ->
    108      * "compute" pic order counts for non-existing frames. These are not
    109      * actually computed, but process needs to be done to update the
    110      * prevFrameNum and prevFrameNumOffset */
    111     if ( sps->picOrderCntType > 0 &&
    112          pSliceHeader->frameNum != poc->prevFrameNum &&
    113          pSliceHeader->frameNum != ((poc->prevFrameNum + 1) % sps->maxFrameNum))
    114     {
    115 
    116         /* use variable i for unUsedShortTermFrameNum */
    117         i = (poc->prevFrameNum + 1) % sps->maxFrameNum;
    118 
    119         do
    120         {
    121             if (poc->prevFrameNum > i)
    122                 frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum;
    123             else
    124                 frameNumOffset = poc->prevFrameNumOffset;
    125 
    126             poc->prevFrameNumOffset = frameNumOffset;
    127             poc->prevFrameNum = i;
    128 
    129             i = (i + 1) % sps->maxFrameNum;
    130 
    131         } while (i != pSliceHeader->frameNum);
    132     }
    133 #endif
    134 
    135     /* check if current slice includes mmco equal to 5 */
    136     containsMmco5 = HANTRO_FALSE;
    137     if (pSliceHeader->decRefPicMarking.adaptiveRefPicMarkingModeFlag)
    138     {
    139         i = 0;
    140         while (pSliceHeader->decRefPicMarking.operation[i].
    141             memoryManagementControlOperation)
    142         {
    143             if (pSliceHeader->decRefPicMarking.operation[i].
    144                 memoryManagementControlOperation == 5)
    145             {
    146                 containsMmco5 = HANTRO_TRUE;
    147                 break;
    148             }
    149             i++;
    150         }
    151     }
    152     switch (sps->picOrderCntType)
    153     {
    154 
    155         case 0:
    156             /* set prevPicOrderCnt values for IDR frame */
    157             if (IS_IDR_NAL_UNIT(pNalUnit))
    158             {
    159                 poc->prevPicOrderCntMsb = 0;
    160                 poc->prevPicOrderCntLsb = 0;
    161             }
    162 
    163             /* compute picOrderCntMsb (stored in picOrderCnt variable) */
    164             if ( (pSliceHeader->picOrderCntLsb < poc->prevPicOrderCntLsb) &&
    165                 ((poc->prevPicOrderCntLsb - pSliceHeader->picOrderCntLsb) >=
    166                  sps->maxPicOrderCntLsb/2) )
    167             {
    168                 picOrderCnt = poc->prevPicOrderCntMsb +
    169                     (i32)sps->maxPicOrderCntLsb;
    170             }
    171             else if ((pSliceHeader->picOrderCntLsb > poc->prevPicOrderCntLsb) &&
    172                 ((pSliceHeader->picOrderCntLsb - poc->prevPicOrderCntLsb) >
    173                  sps->maxPicOrderCntLsb/2) )
    174             {
    175                 picOrderCnt = poc->prevPicOrderCntMsb -
    176                     (i32)sps->maxPicOrderCntLsb;
    177             }
    178             else
    179                 picOrderCnt = poc->prevPicOrderCntMsb;
    180 
    181             /* standard specifies that prevPicOrderCntMsb is from previous
    182              * rererence frame -> replace old value only if current frame is
    183              * rererence frame */
    184             if (pNalUnit->nalRefIdc)
    185                 poc->prevPicOrderCntMsb = picOrderCnt;
    186 
    187             /* compute top field order cnt (stored in picOrderCnt) */
    188             picOrderCnt += (i32)pSliceHeader->picOrderCntLsb;
    189 
    190             /* if delta for bottom field is negative -> bottom will be the
    191              * minimum pic order count */
    192             if (pSliceHeader->deltaPicOrderCntBottom < 0)
    193                 picOrderCnt += pSliceHeader->deltaPicOrderCntBottom;
    194 
    195             /* standard specifies that prevPicOrderCntLsb is from previous
    196              * rererence frame -> replace old value only if current frame is
    197              * rererence frame */
    198             if (pNalUnit->nalRefIdc)
    199             {
    200                 /* if current frame contains mmco5 -> modify values to be
    201                  * stored */
    202                 if (containsMmco5)
    203                 {
    204                     poc->prevPicOrderCntMsb = 0;
    205                     /* prevPicOrderCntLsb should be the top field picOrderCnt
    206                      * if previous frame included mmco5. Top field picOrderCnt
    207                      * for frames containing mmco5 is obtained by subtracting
    208                      * the picOrderCnt from original top field order count ->
    209                      * value is zero if top field was the minimum, i.e. delta
    210                      * for bottom was positive, otherwise value is
    211                      * -deltaPicOrderCntBottom */
    212                     if (pSliceHeader->deltaPicOrderCntBottom < 0)
    213                         poc->prevPicOrderCntLsb =
    214                             (u32)(-pSliceHeader->deltaPicOrderCntBottom);
    215                     else
    216                         poc->prevPicOrderCntLsb = 0;
    217                     picOrderCnt = 0;
    218                 }
    219                 else
    220                 {
    221                     poc->prevPicOrderCntLsb = pSliceHeader->picOrderCntLsb;
    222                 }
    223             }
    224 
    225             break;
    226 
    227         case 1:
    228 
    229             /* step 1 (in the description in the standard) */
    230             if (IS_IDR_NAL_UNIT(pNalUnit))
    231                 frameNumOffset = 0;
    232             else if (poc->prevFrameNum > pSliceHeader->frameNum)
    233                 frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum;
    234             else
    235                 frameNumOffset = poc->prevFrameNumOffset;
    236 
    237             /* step 2 */
    238             if (sps->numRefFramesInPicOrderCntCycle)
    239                 absFrameNum = frameNumOffset + pSliceHeader->frameNum;
    240             else
    241                 absFrameNum = 0;
    242 
    243             if (pNalUnit->nalRefIdc == 0 && absFrameNum > 0)
    244                 absFrameNum -= 1;
    245 
    246             /* step 3 */
    247             if (absFrameNum > 0)
    248             {
    249                 picOrderCntCycleCnt =
    250                     (absFrameNum - 1)/sps->numRefFramesInPicOrderCntCycle;
    251                 frameNumInPicOrderCntCycle =
    252                     (absFrameNum - 1)%sps->numRefFramesInPicOrderCntCycle;
    253             }
    254 
    255             /* step 4 */
    256             expectedDeltaPicOrderCntCycle = 0;
    257             for (i = 0; i < sps->numRefFramesInPicOrderCntCycle; i++)
    258                 expectedDeltaPicOrderCntCycle += sps->offsetForRefFrame[i];
    259 
    260             /* step 5 (picOrderCnt used to store expectedPicOrderCnt) */
    261             /*lint -esym(644,picOrderCntCycleCnt) always initialized */
    262             /*lint -esym(644,frameNumInPicOrderCntCycle) always initialized */
    263             if (absFrameNum > 0)
    264             {
    265                 picOrderCnt =
    266                     (i32)picOrderCntCycleCnt * expectedDeltaPicOrderCntCycle;
    267                 for (i = 0; i <= frameNumInPicOrderCntCycle; i++)
    268                     picOrderCnt += sps->offsetForRefFrame[i];
    269             }
    270             else
    271                 picOrderCnt = 0;
    272 
    273             if (pNalUnit->nalRefIdc == 0)
    274                 picOrderCnt += sps->offsetForNonRefPic;
    275 
    276             /* step 6 (picOrderCnt is top field order cnt if delta for bottom
    277              * is positive, otherwise it is bottom field order cnt) */
    278             picOrderCnt += pSliceHeader->deltaPicOrderCnt[0];
    279 
    280             if ( (sps->offsetForTopToBottomField +
    281                     pSliceHeader->deltaPicOrderCnt[1]) < 0 )
    282             {
    283                 picOrderCnt += sps->offsetForTopToBottomField +
    284                     pSliceHeader->deltaPicOrderCnt[1];
    285             }
    286 
    287             /* if current picture contains mmco5 -> set prevFrameNumOffset and
    288              * prevFrameNum to 0 for computation of picOrderCnt of next
    289              * frame, otherwise store frameNum and frameNumOffset to poc
    290              * structure */
    291             if (!containsMmco5)
    292             {
    293                 poc->prevFrameNumOffset = frameNumOffset;
    294                 poc->prevFrameNum = pSliceHeader->frameNum;
    295             }
    296             else
    297             {
    298                 poc->prevFrameNumOffset = 0;
    299                 poc->prevFrameNum = 0;
    300                 picOrderCnt = 0;
    301             }
    302             break;
    303 
    304         default: /* case 2 */
    305             /* derive frameNumOffset */
    306             if (IS_IDR_NAL_UNIT(pNalUnit))
    307                 frameNumOffset = 0;
    308             else if (poc->prevFrameNum > pSliceHeader->frameNum)
    309                 frameNumOffset = poc->prevFrameNumOffset + sps->maxFrameNum;
    310             else
    311                 frameNumOffset = poc->prevFrameNumOffset;
    312 
    313             /* derive picOrderCnt (type 2 has same value for top and bottom
    314              * field order cnts) */
    315             if (IS_IDR_NAL_UNIT(pNalUnit))
    316                 picOrderCnt = 0;
    317             else if (pNalUnit->nalRefIdc == 0)
    318                 picOrderCnt =
    319                     2 * (i32)(frameNumOffset + pSliceHeader->frameNum) - 1;
    320             else
    321                 picOrderCnt =
    322                     2 * (i32)(frameNumOffset + pSliceHeader->frameNum);
    323 
    324             /* if current picture contains mmco5 -> set prevFrameNumOffset and
    325              * prevFrameNum to 0 for computation of picOrderCnt of next
    326              * frame, otherwise store frameNum and frameNumOffset to poc
    327              * structure */
    328             if (!containsMmco5)
    329             {
    330                 poc->prevFrameNumOffset = frameNumOffset;
    331                 poc->prevFrameNum = pSliceHeader->frameNum;
    332             }
    333             else
    334             {
    335                 poc->prevFrameNumOffset = 0;
    336                 poc->prevFrameNum = 0;
    337                 picOrderCnt = 0;
    338             }
    339             break;
    340 
    341     }
    342 
    343     /*lint -esym(644,picOrderCnt) always initialized */
    344     return(picOrderCnt);
    345 
    346 }
    347 
    348