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 
h264bsdDecodePicOrderCnt(pocStorage_t * poc,seqParamSet_t * sps,sliceHeader_t * pSliceHeader,nalUnit_t * pNalUnit)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