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           h264bsdDecodePicParamSet
27 
28 ------------------------------------------------------------------------------*/
29 
30 /*------------------------------------------------------------------------------
31     1. Include headers
32 ------------------------------------------------------------------------------*/
33 
34 #include "h264bsd_pic_param_set.h"
35 #include "h264bsd_util.h"
36 #include "h264bsd_vlc.h"
37 #include "h264bsd_cfg.h"
38 
39 /*------------------------------------------------------------------------------
40     2. External compiler flags
41 --------------------------------------------------------------------------------
42 
43 --------------------------------------------------------------------------------
44     3. Module defines
45 ------------------------------------------------------------------------------*/
46 
47 /* lookup table for ceil(log2(numSliceGroups)), i.e. number of bits needed to
48  * represent range [0, numSliceGroups)
49  *
50  * NOTE: if MAX_NUM_SLICE_GROUPS is higher than 8 this table has to be resized
51  * accordingly */
52 static const u32 CeilLog2NumSliceGroups[8] = {1, 1, 2, 2, 3, 3, 3, 3};
53 
54 /*------------------------------------------------------------------------------
55     4. Local function prototypes
56 ------------------------------------------------------------------------------*/
57 
58 /*------------------------------------------------------------------------------
59 
60     Function name: h264bsdDecodePicParamSet
61 
62         Functional description:
63             Decode picture parameter set information from the stream.
64 
65             Function allocates memory for
66                 - run lengths if slice group map type is 0
67                 - top-left and bottom-right arrays if map type is 2
68                 - for slice group ids if map type is 6
69 
70             Validity of some of the slice group mapping information depends
71             on the image dimensions which are not known here. Therefore the
72             validity has to be checked afterwards, currently in the parameter
73             set activation phase.
74 
75         Inputs:
76             pStrmData       pointer to stream data structure
77 
78         Outputs:
79             pPicParamSet    decoded information is stored here
80 
81         Returns:
82             HANTRO_OK       success
83             HANTRO_NOK      failure, invalid information or end of stream
84             MEMORY_ALLOCATION_ERROR for memory allocation failure
85 
86 
87 ------------------------------------------------------------------------------*/
88 
h264bsdDecodePicParamSet(strmData_t * pStrmData,picParamSet_t * pPicParamSet)89 u32 h264bsdDecodePicParamSet(strmData_t *pStrmData, picParamSet_t *pPicParamSet)
90 {
91 
92 /* Variables */
93 
94     u32 tmp, i, value;
95     i32 itmp;
96 
97 /* Code */
98 
99     ASSERT(pStrmData);
100     ASSERT(pPicParamSet);
101 
102 
103     H264SwDecMemset(pPicParamSet, 0, sizeof(picParamSet_t));
104 
105     tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
106         &pPicParamSet->picParameterSetId);
107     if (tmp != HANTRO_OK)
108         return(tmp);
109     if (pPicParamSet->picParameterSetId >= MAX_NUM_PIC_PARAM_SETS)
110     {
111         EPRINT("pic_parameter_set_id");
112         return(HANTRO_NOK);
113     }
114 
115     tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
116         &pPicParamSet->seqParameterSetId);
117     if (tmp != HANTRO_OK)
118         return(tmp);
119     if (pPicParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS)
120     {
121         EPRINT("seq_param_set_id");
122         return(HANTRO_NOK);
123     }
124 
125     /* entropy_coding_mode_flag, shall be 0 for baseline profile */
126     tmp = h264bsdGetBits(pStrmData, 1);
127     if (tmp)
128     {
129         EPRINT("entropy_coding_mode_flag");
130         return(HANTRO_NOK);
131     }
132 
133     tmp = h264bsdGetBits(pStrmData, 1);
134     if (tmp == END_OF_STREAM)
135         return(HANTRO_NOK);
136     pPicParamSet->picOrderPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
137 
138     /* num_slice_groups_minus1 */
139     tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
140     if (tmp != HANTRO_OK)
141         return(tmp);
142     pPicParamSet->numSliceGroups = value + 1;
143     if (pPicParamSet->numSliceGroups > MAX_NUM_SLICE_GROUPS)
144     {
145         EPRINT("num_slice_groups_minus1");
146         return(HANTRO_NOK);
147     }
148 
149     /* decode slice group mapping information if more than one slice groups */
150     if (pPicParamSet->numSliceGroups > 1)
151     {
152         tmp = h264bsdDecodeExpGolombUnsigned(pStrmData,
153             &pPicParamSet->sliceGroupMapType);
154         if (tmp != HANTRO_OK)
155             return(tmp);
156         if (pPicParamSet->sliceGroupMapType > 6)
157         {
158             EPRINT("slice_group_map_type");
159             return(HANTRO_NOK);
160         }
161 
162         if (pPicParamSet->sliceGroupMapType == 0)
163         {
164             ALLOCATE(pPicParamSet->runLength,
165                 pPicParamSet->numSliceGroups, u32);
166             if (pPicParamSet->runLength == NULL)
167                 return(MEMORY_ALLOCATION_ERROR);
168             for (i = 0; i < pPicParamSet->numSliceGroups; i++)
169             {
170                 tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
171                 if (tmp != HANTRO_OK)
172                     return(tmp);
173                 pPicParamSet->runLength[i] = value+1;
174                 /* param values checked in CheckPps() */
175             }
176         }
177         else if (pPicParamSet->sliceGroupMapType == 2)
178         {
179             ALLOCATE(pPicParamSet->topLeft,
180                 pPicParamSet->numSliceGroups - 1, u32);
181             ALLOCATE(pPicParamSet->bottomRight,
182                 pPicParamSet->numSliceGroups - 1, u32);
183             if (pPicParamSet->topLeft == NULL ||
184                 pPicParamSet->bottomRight == NULL)
185                 return(MEMORY_ALLOCATION_ERROR);
186             for (i = 0; i < pPicParamSet->numSliceGroups - 1; i++)
187             {
188                 tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
189                 if (tmp != HANTRO_OK)
190                     return(tmp);
191                 pPicParamSet->topLeft[i] = value;
192                 tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
193                 if (tmp != HANTRO_OK)
194                     return(tmp);
195                 pPicParamSet->bottomRight[i] = value;
196                 /* param values checked in CheckPps() */
197             }
198         }
199         else if ( (pPicParamSet->sliceGroupMapType == 3) ||
200                   (pPicParamSet->sliceGroupMapType == 4) ||
201                   (pPicParamSet->sliceGroupMapType == 5) )
202         {
203             tmp = h264bsdGetBits(pStrmData, 1);
204             if (tmp == END_OF_STREAM)
205                 return(HANTRO_NOK);
206             pPicParamSet->sliceGroupChangeDirectionFlag =
207                 (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
208             tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
209             if (tmp != HANTRO_OK)
210                 return(tmp);
211             pPicParamSet->sliceGroupChangeRate = value + 1;
212             /* param value checked in CheckPps() */
213         }
214         else if (pPicParamSet->sliceGroupMapType == 6)
215         {
216             tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
217             if (tmp != HANTRO_OK)
218                 return(tmp);
219             pPicParamSet->picSizeInMapUnits = value + 1;
220 
221             ALLOCATE(pPicParamSet->sliceGroupId,
222                 pPicParamSet->picSizeInMapUnits, u32);
223             if (pPicParamSet->sliceGroupId == NULL)
224                 return(MEMORY_ALLOCATION_ERROR);
225 
226             /* determine number of bits needed to represent range
227              * [0, numSliceGroups) */
228             tmp = CeilLog2NumSliceGroups[pPicParamSet->numSliceGroups-1];
229 
230             for (i = 0; i < pPicParamSet->picSizeInMapUnits; i++)
231             {
232                 pPicParamSet->sliceGroupId[i] = h264bsdGetBits(pStrmData, tmp);
233                 if ( pPicParamSet->sliceGroupId[i] >=
234                      pPicParamSet->numSliceGroups )
235                 {
236                     EPRINT("slice_group_id");
237                     return(HANTRO_NOK);
238                 }
239             }
240         }
241     }
242 
243     /* num_ref_idx_l0_active_minus1 */
244     tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
245     if (tmp != HANTRO_OK)
246         return(tmp);
247     if (value > 31)
248     {
249         EPRINT("num_ref_idx_l0_active_minus1");
250         return(HANTRO_NOK);
251     }
252     pPicParamSet->numRefIdxL0Active = value + 1;
253 
254     /* num_ref_idx_l1_active_minus1 */
255     tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value);
256     if (tmp != HANTRO_OK)
257         return(tmp);
258     if (value > 31)
259     {
260         EPRINT("num_ref_idx_l1_active_minus1");
261         return(HANTRO_NOK);
262     }
263 
264     /* weighted_pred_flag, this shall be 0 for baseline profile */
265     tmp = h264bsdGetBits(pStrmData, 1);
266     if (tmp)
267     {
268         EPRINT("weighted_pred_flag");
269         return(HANTRO_NOK);
270     }
271 
272     /* weighted_bipred_idc */
273     tmp = h264bsdGetBits(pStrmData, 2);
274     if (tmp > 2)
275     {
276         EPRINT("weighted_bipred_idc");
277         return(HANTRO_NOK);
278     }
279 
280     /* pic_init_qp_minus26 */
281     tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
282     if (tmp != HANTRO_OK)
283         return(tmp);
284     if ((itmp < -26) || (itmp > 25))
285     {
286         EPRINT("pic_init_qp_minus26");
287         return(HANTRO_NOK);
288     }
289     pPicParamSet->picInitQp = (u32)(itmp + 26);
290 
291     /* pic_init_qs_minus26 */
292     tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
293     if (tmp != HANTRO_OK)
294         return(tmp);
295     if ((itmp < -26) || (itmp > 25))
296     {
297         EPRINT("pic_init_qs_minus26");
298         return(HANTRO_NOK);
299     }
300 
301     tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp);
302     if (tmp != HANTRO_OK)
303         return(tmp);
304     if ((itmp < -12) || (itmp > 12))
305     {
306         EPRINT("chroma_qp_index_offset");
307         return(HANTRO_NOK);
308     }
309     pPicParamSet->chromaQpIndexOffset = itmp;
310 
311     tmp = h264bsdGetBits(pStrmData, 1);
312     if (tmp == END_OF_STREAM)
313         return(HANTRO_NOK);
314     pPicParamSet->deblockingFilterControlPresentFlag =
315         (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE;
316 
317     tmp = h264bsdGetBits(pStrmData, 1);
318     if (tmp == END_OF_STREAM)
319         return(HANTRO_NOK);
320     pPicParamSet->constrainedIntraPredFlag = (tmp == 1) ?
321                                     HANTRO_TRUE : HANTRO_FALSE;
322 
323     tmp = h264bsdGetBits(pStrmData, 1);
324     if (tmp == END_OF_STREAM)
325         return(HANTRO_NOK);
326     pPicParamSet->redundantPicCntPresentFlag = (tmp == 1) ?
327                                     HANTRO_TRUE : HANTRO_FALSE;
328 
329     tmp = h264bsdRbspTrailingBits(pStrmData);
330 
331     /* ignore possible errors in trailing bits of parameters sets */
332     return(HANTRO_OK);
333 
334 }
335 
336