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
52static 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
85u32 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
253void 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
297void 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