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 h264bsdDecodeSliceData
27 SetMbParams
28 h264bsdMarkSliceCorrupted
29
30 ------------------------------------------------------------------------------*/
31
32 /*------------------------------------------------------------------------------
33 1. Include headers
34 ------------------------------------------------------------------------------*/
35
36 #include "h264bsd_slice_data.h"
37 #include "h264bsd_util.h"
38 #include "h264bsd_vlc.h"
39
40 /*------------------------------------------------------------------------------
41 2. External compiler flags
42 --------------------------------------------------------------------------------
43
44 --------------------------------------------------------------------------------
45 3. Module defines
46 ------------------------------------------------------------------------------*/
47
48 /*------------------------------------------------------------------------------
49 4. Local function prototypes
50 ------------------------------------------------------------------------------*/
51
52 static void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId,
53 i32 chromaQpIndexOffset);
54
55 /*------------------------------------------------------------------------------
56
57 5.1 Function name: h264bsdDecodeSliceData
58
59 Functional description:
60 Decode one slice. Function decodes stream data, i.e. macroblocks
61 and possible skip_run fields. h264bsdDecodeMacroblock function is
62 called to handle all other macroblock related processing.
63 Macroblock to slice group mapping is considered when next
64 macroblock to process is determined (h264bsdNextMbAddress function)
65 map
66
67 Inputs:
68 pStrmData pointer to stream data structure
69 pStorage pointer to storage structure
70 currImage pointer to current processed picture, needed for
71 intra prediction of the macroblocks
72 pSliceHeader pointer to slice header of the current slice
73
74 Outputs:
75 currImage processed macroblocks are written to current image
76 pStorage mbStorage structure of each processed macroblock
77 is updated here
78
79 Returns:
80 HANTRO_OK success
81 HANTRO_NOK invalid stream data
82
83 ------------------------------------------------------------------------------*/
84
h264bsdDecodeSliceData(strmData_t * pStrmData,storage_t * pStorage,image_t * currImage,sliceHeader_t * pSliceHeader)85 u32 h264bsdDecodeSliceData(strmData_t *pStrmData, storage_t *pStorage,
86 image_t *currImage, sliceHeader_t *pSliceHeader)
87 {
88
89 /* Variables */
90
91 u8 mbData[384 + 15 + 32];
92 u8 *data;
93 u32 tmp;
94 u32 skipRun;
95 u32 prevSkipped;
96 u32 currMbAddr;
97 u32 moreMbs;
98 u32 mbCount;
99 i32 qpY;
100 macroblockLayer_t *mbLayer;
101
102 /* Code */
103
104 ASSERT(pStrmData);
105 ASSERT(pSliceHeader);
106 ASSERT(pStorage);
107 ASSERT(pSliceHeader->firstMbInSlice < pStorage->picSizeInMbs);
108
109 /* ensure 16-byte alignment */
110 data = (u8*)ALIGN(mbData, 16);
111
112 mbLayer = pStorage->mbLayer;
113
114 currMbAddr = pSliceHeader->firstMbInSlice;
115 skipRun = 0;
116 prevSkipped = HANTRO_FALSE;
117
118 /* increment slice index, will be one for decoding of the first slice of
119 * the picture */
120 pStorage->slice->sliceId++;
121
122 /* lastMbAddr stores address of the macroblock that was last successfully
123 * decoded, needed for error handling */
124 pStorage->slice->lastMbAddr = 0;
125
126 mbCount = 0;
127 /* initial quantization parameter for the slice is obtained as the sum of
128 * initial QP for the picture and sliceQpDelta for the current slice */
129 qpY = (i32)pStorage->activePps->picInitQp + pSliceHeader->sliceQpDelta;
130 do
131 {
132 /* primary picture and already decoded macroblock -> error */
133 if (!pSliceHeader->redundantPicCnt && pStorage->mb[currMbAddr].decoded)
134 {
135 EPRINT("Primary and already decoded");
136 return(HANTRO_NOK);
137 }
138
139 SetMbParams(pStorage->mb + currMbAddr, pSliceHeader,
140 pStorage->slice->sliceId, pStorage->activePps->chromaQpIndexOffset);
141
142 if (!IS_I_SLICE(pSliceHeader->sliceType))
143 {
144 if (!prevSkipped)
145 {
146 tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &skipRun);
147 if (tmp != HANTRO_OK)
148 return(tmp);
149 /* skip_run shall be less than or equal to number of
150 * macroblocks left */
151 if (skipRun > (pStorage->picSizeInMbs - currMbAddr))
152 {
153 EPRINT("skip_run");
154 return(HANTRO_NOK);
155 }
156 if (skipRun)
157 {
158 prevSkipped = HANTRO_TRUE;
159 H264SwDecMemset(&mbLayer->mbPred, 0, sizeof(mbPred_t));
160 /* mark current macroblock skipped */
161 mbLayer->mbType = P_Skip;
162 }
163 }
164 }
165
166 if (skipRun)
167 {
168 DEBUG(("Skipping macroblock %d\n", currMbAddr));
169 skipRun--;
170 }
171 else
172 {
173 prevSkipped = HANTRO_FALSE;
174 tmp = h264bsdDecodeMacroblockLayer(pStrmData, mbLayer,
175 pStorage->mb + currMbAddr, pSliceHeader->sliceType,
176 pSliceHeader->numRefIdxL0Active);
177 if (tmp != HANTRO_OK)
178 {
179 EPRINT("macroblock_layer");
180 return(tmp);
181 }
182 }
183
184 tmp = h264bsdDecodeMacroblock(pStorage->mb + currMbAddr, mbLayer,
185 currImage, pStorage->dpb, &qpY, currMbAddr,
186 pStorage->activePps->constrainedIntraPredFlag, data);
187 if (tmp != HANTRO_OK)
188 {
189 EPRINT("MACRO_BLOCK");
190 return(tmp);
191 }
192
193 /* increment macroblock count only for macroblocks that were decoded
194 * for the first time (redundant slices) */
195 if (pStorage->mb[currMbAddr].decoded == 1)
196 mbCount++;
197
198 /* keep on processing as long as there is stream data left or
199 * processing of macroblocks to be skipped based on the last skipRun is
200 * not finished */
201 moreMbs = (h264bsdMoreRbspData(pStrmData) || skipRun) ?
202 HANTRO_TRUE : HANTRO_FALSE;
203
204 /* lastMbAddr is only updated for intra slices (all macroblocks of
205 * inter slices will be lost in case of an error) */
206 if (IS_I_SLICE(pSliceHeader->sliceType))
207 pStorage->slice->lastMbAddr = currMbAddr;
208
209 currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap,
210 pStorage->picSizeInMbs, currMbAddr);
211 /* data left in the buffer but no more macroblocks for current slice
212 * group -> error */
213 if (moreMbs && !currMbAddr)
214 {
215 EPRINT("Next mb address");
216 return(HANTRO_NOK);
217 }
218
219 } while (moreMbs);
220
221 if ((pStorage->slice->numDecodedMbs + mbCount) > pStorage->picSizeInMbs)
222 {
223 EPRINT("Num decoded mbs");
224 return(HANTRO_NOK);
225 }
226
227 pStorage->slice->numDecodedMbs += mbCount;
228
229 return(HANTRO_OK);
230
231 }
232
233 /*------------------------------------------------------------------------------
234
235 5.2 Function: SetMbParams
236
237 Functional description:
238 Set macroblock parameters that remain constant for this slice
239
240 Inputs:
241 pSlice pointer to current slice header
242 sliceId id of the current slice
243 chromaQpIndexOffset
244
245 Outputs:
246 pMb pointer to macroblock structure which is updated
247
248 Returns:
249 none
250
251 ------------------------------------------------------------------------------*/
252
SetMbParams(mbStorage_t * pMb,sliceHeader_t * pSlice,u32 sliceId,i32 chromaQpIndexOffset)253 void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId,
254 i32 chromaQpIndexOffset)
255 {
256
257 /* Variables */
258 u32 tmp1;
259 i32 tmp2, tmp3;
260
261 /* Code */
262
263 tmp1 = pSlice->disableDeblockingFilterIdc;
264 tmp2 = pSlice->sliceAlphaC0Offset;
265 tmp3 = pSlice->sliceBetaOffset;
266 pMb->sliceId = sliceId;
267 pMb->disableDeblockingFilterIdc = tmp1;
268 pMb->filterOffsetA = tmp2;
269 pMb->filterOffsetB = tmp3;
270 pMb->chromaQpIndexOffset = chromaQpIndexOffset;
271
272 }
273
274 /*------------------------------------------------------------------------------
275
276 5.3 Function name: h264bsdMarkSliceCorrupted
277
278 Functional description:
279 Mark macroblocks of the slice corrupted. If lastMbAddr in the slice
280 storage is set -> picWidhtInMbs (or at least 10) macroblocks back
281 from the lastMbAddr are marked corrupted. However, if lastMbAddr
282 is not set -> all macroblocks of the slice are marked.
283
284 Inputs:
285 pStorage pointer to storage structure
286 firstMbInSlice address of the first macroblock in the slice, this
287 identifies the slice to be marked corrupted
288
289 Outputs:
290 pStorage mbStorage for the corrupted macroblocks updated
291
292 Returns:
293 none
294
295 ------------------------------------------------------------------------------*/
296
h264bsdMarkSliceCorrupted(storage_t * pStorage,u32 firstMbInSlice)297 void h264bsdMarkSliceCorrupted(storage_t *pStorage, u32 firstMbInSlice)
298 {
299
300 /* Variables */
301
302 u32 tmp, i;
303 u32 sliceId;
304 u32 currMbAddr;
305
306 /* Code */
307
308 ASSERT(pStorage);
309 ASSERT(firstMbInSlice < pStorage->picSizeInMbs);
310
311 currMbAddr = firstMbInSlice;
312
313 sliceId = pStorage->slice->sliceId;
314
315 /* DecodeSliceData sets lastMbAddr for I slices -> if it was set, go back
316 * MAX(picWidthInMbs, 10) macroblocks and start marking from there */
317 if (pStorage->slice->lastMbAddr)
318 {
319 ASSERT(pStorage->mb[pStorage->slice->lastMbAddr].sliceId == sliceId);
320 i = pStorage->slice->lastMbAddr - 1;
321 tmp = 0;
322 while (i > currMbAddr)
323 {
324 if (pStorage->mb[i].sliceId == sliceId)
325 {
326 tmp++;
327 if (tmp >= MAX(pStorage->activeSps->picWidthInMbs, 10))
328 break;
329 }
330 i--;
331 }
332 currMbAddr = i;
333 }
334
335 do
336 {
337
338 if ( (pStorage->mb[currMbAddr].sliceId == sliceId) &&
339 (pStorage->mb[currMbAddr].decoded) )
340 {
341 pStorage->mb[currMbAddr].decoded--;
342 }
343 else
344 {
345 break;
346 }
347
348 currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap,
349 pStorage->picSizeInMbs, currMbAddr);
350
351 } while (currMbAddr);
352
353 }
354
355