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