h264bsd_pic_order_cnt.c revision 21e525fdcc234c22d843a8bf1a4ec35c4b376314
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
79i32 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