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          DecodeInterleavedMap
27          DecodeDispersedMap
28          DecodeForegroundLeftOverMap
29          DecodeBoxOutMap
30          DecodeRasterScanMap
31          DecodeWipeMap
32          h264bsdDecodeSliceGroupMap
33
34------------------------------------------------------------------------------*/
35
36/*------------------------------------------------------------------------------
37    1. Include headers
38------------------------------------------------------------------------------*/
39
40#include "basetype.h"
41#include "h264bsd_slice_group_map.h"
42#include "h264bsd_cfg.h"
43#include "h264bsd_pic_param_set.h"
44#include "h264bsd_util.h"
45
46/*------------------------------------------------------------------------------
47    2. External compiler flags
48--------------------------------------------------------------------------------
49
50--------------------------------------------------------------------------------
51    3. Module defines
52------------------------------------------------------------------------------*/
53
54/*------------------------------------------------------------------------------
55    4. Local function prototypes
56------------------------------------------------------------------------------*/
57
58static void DecodeInterleavedMap(
59  u32 *map,
60  u32 numSliceGroups,
61  u32 *runLength,
62  u32 picSize);
63
64static void DecodeDispersedMap(
65  u32 *map,
66  u32 numSliceGroups,
67  u32 picWidth,
68  u32 picHeight);
69
70static void DecodeForegroundLeftOverMap(
71  u32 *map,
72  u32 numSliceGroups,
73  u32 *topLeft,
74  u32 *bottomRight,
75  u32 picWidth,
76  u32 picHeight);
77
78static void DecodeBoxOutMap(
79  u32 *map,
80  u32 sliceGroupChangeDirectionFlag,
81  u32 unitsInSliceGroup0,
82  u32 picWidth,
83  u32 picHeight);
84
85static void DecodeRasterScanMap(
86  u32 *map,
87  u32 sliceGroupChangeDirectionFlag,
88  u32 sizeOfUpperLeftGroup,
89  u32 picSize);
90
91static void DecodeWipeMap(
92  u32 *map,
93  u32 sliceGroupChangeDirectionFlag,
94  u32 sizeOfUpperLeftGroup,
95  u32 picWidth,
96  u32 picHeight);
97
98/*------------------------------------------------------------------------------
99
100    Function: DecodeInterleavedMap
101
102        Functional description:
103            Function to decode interleaved slice group map type, i.e. slice
104            group map type 0.
105
106        Inputs:
107            map             pointer to the map
108            numSliceGroups  number of slice groups
109            runLength       run_length[] values for each slice group
110            picSize         picture size in macroblocks
111
112        Outputs:
113            map             slice group map is stored here
114
115        Returns:
116            none
117
118------------------------------------------------------------------------------*/
119
120void DecodeInterleavedMap(
121  u32 *map,
122  u32 numSliceGroups,
123  u32 *runLength,
124  u32 picSize)
125{
126
127/* Variables */
128
129    u32 i,j, group;
130
131/* Code */
132
133    ASSERT(map);
134    ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
135    ASSERT(runLength);
136
137    i = 0;
138
139    do {
140        for (group = 0; group < numSliceGroups && i < picSize;
141          i += runLength[group++])
142        {
143            ASSERT(runLength[group] <= picSize);
144            for (j = 0; j < runLength[group] && i + j < picSize; j++)
145                map[i+j] = group;
146        }
147    } while (i < picSize);
148
149
150}
151
152/*------------------------------------------------------------------------------
153
154    Function: DecodeDispersedMap
155
156        Functional description:
157            Function to decode dispersed slice group map type, i.e. slice
158            group map type 1.
159
160        Inputs:
161            map               pointer to the map
162            numSliceGroups    number of slice groups
163            picWidth          picture width in macroblocks
164            picHeight         picture height in macroblocks
165
166        Outputs:
167            map               slice group map is stored here
168
169        Returns:
170            none
171
172------------------------------------------------------------------------------*/
173
174void DecodeDispersedMap(
175  u32 *map,
176  u32 numSliceGroups,
177  u32 picWidth,
178  u32 picHeight)
179{
180
181/* Variables */
182
183    u32 i, picSize;
184
185/* Code */
186
187    ASSERT(map);
188    ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
189    ASSERT(picWidth);
190    ASSERT(picHeight);
191
192    picSize = picWidth * picHeight;
193
194    for (i = 0; i < picSize; i++)
195        map[i] = ((i % picWidth) + (((i / picWidth) * numSliceGroups) >> 1)) %
196            numSliceGroups;
197
198
199}
200
201/*------------------------------------------------------------------------------
202
203    Function: DecodeForegroundLeftOverMap
204
205        Functional description:
206            Function to decode foreground with left-over slice group map type,
207            i.e. slice group map type 2.
208
209        Inputs:
210            map               pointer to the map
211            numSliceGroups    number of slice groups
212            topLeft           top_left[] values
213            bottomRight       bottom_right[] values
214            picWidth          picture width in macroblocks
215            picHeight         picture height in macroblocks
216
217        Outputs:
218            map               slice group map is stored here
219
220        Returns:
221            none
222
223------------------------------------------------------------------------------*/
224
225void DecodeForegroundLeftOverMap(
226  u32 *map,
227  u32 numSliceGroups,
228  u32 *topLeft,
229  u32 *bottomRight,
230  u32 picWidth,
231  u32 picHeight)
232{
233
234/* Variables */
235
236    u32 i,y,x,yTopLeft,yBottomRight,xTopLeft,xBottomRight, picSize;
237    u32 group;
238
239/* Code */
240
241    ASSERT(map);
242    ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
243    ASSERT(topLeft);
244    ASSERT(bottomRight);
245    ASSERT(picWidth);
246    ASSERT(picHeight);
247
248    picSize = picWidth * picHeight;
249
250    for (i = 0; i < picSize; i++)
251        map[i] = numSliceGroups - 1;
252
253    for (group = numSliceGroups - 1; group--; )
254    {
255        ASSERT( topLeft[group] <= bottomRight[group] &&
256                bottomRight[group] < picSize );
257        yTopLeft = topLeft[group] / picWidth;
258        xTopLeft = topLeft[group] % picWidth;
259        yBottomRight = bottomRight[group] / picWidth;
260        xBottomRight = bottomRight[group] % picWidth;
261        ASSERT(xTopLeft <= xBottomRight);
262
263        for (y = yTopLeft; y <= yBottomRight; y++)
264            for (x = xTopLeft; x <= xBottomRight; x++)
265                map[ y * picWidth + x ] = group;
266    }
267
268
269}
270
271/*------------------------------------------------------------------------------
272
273    Function: DecodeBoxOutMap
274
275        Functional description:
276            Function to decode box-out slice group map type, i.e. slice group
277            map type 3.
278
279        Inputs:
280            map                               pointer to the map
281            sliceGroupChangeDirectionFlag     slice_group_change_direction_flag
282            unitsInSliceGroup0                mbs on slice group 0
283            picWidth                          picture width in macroblocks
284            picHeight                         picture height in macroblocks
285
286        Outputs:
287            map                               slice group map is stored here
288
289        Returns:
290            none
291
292------------------------------------------------------------------------------*/
293
294void DecodeBoxOutMap(
295  u32 *map,
296  u32 sliceGroupChangeDirectionFlag,
297  u32 unitsInSliceGroup0,
298  u32 picWidth,
299  u32 picHeight)
300{
301
302/* Variables */
303
304    u32 i, k, picSize;
305    i32 x, y, xDir, yDir, leftBound, topBound, rightBound, bottomBound;
306    u32 mapUnitVacant;
307
308/* Code */
309
310    ASSERT(map);
311    ASSERT(picWidth);
312    ASSERT(picHeight);
313
314    picSize = picWidth * picHeight;
315    ASSERT(unitsInSliceGroup0 <= picSize);
316
317    for (i = 0; i < picSize; i++)
318        map[i] = 1;
319
320    x = (picWidth - (u32)sliceGroupChangeDirectionFlag) >> 1;
321    y = (picHeight - (u32)sliceGroupChangeDirectionFlag) >> 1;
322
323    leftBound = x;
324    topBound = y;
325
326    rightBound = x;
327    bottomBound = y;
328
329    xDir = (i32)sliceGroupChangeDirectionFlag - 1;
330    yDir = (i32)sliceGroupChangeDirectionFlag;
331
332    for (k = 0; k < unitsInSliceGroup0; k += mapUnitVacant ? 1 : 0)
333    {
334        mapUnitVacant = (map[ (u32)y * picWidth + (u32)x ] == 1) ?
335                                        HANTRO_TRUE : HANTRO_FALSE;
336
337        if (mapUnitVacant)
338            map[ (u32)y * picWidth + (u32)x ] = 0;
339
340        if (xDir == -1 && x == leftBound)
341        {
342            leftBound = MAX(leftBound - 1, 0);
343            x = leftBound;
344            xDir = 0;
345            yDir = 2 * (i32)sliceGroupChangeDirectionFlag - 1;
346        }
347        else if (xDir == 1 && x == rightBound)
348        {
349            rightBound = MIN(rightBound + 1, (i32)picWidth - 1);
350            x = rightBound;
351            xDir = 0;
352            yDir = 1 - 2 * (i32)sliceGroupChangeDirectionFlag;
353        }
354        else if (yDir == -1 && y == topBound)
355        {
356            topBound = MAX(topBound - 1, 0);
357            y = topBound;
358            xDir = 1 - 2 * (i32)sliceGroupChangeDirectionFlag;
359            yDir = 0;
360        }
361        else if (yDir == 1 && y == bottomBound)
362        {
363            bottomBound = MIN(bottomBound + 1, (i32)picHeight - 1);
364            y = bottomBound;
365            xDir = 2 * (i32)sliceGroupChangeDirectionFlag - 1;
366            yDir = 0;
367        }
368        else
369        {
370            x += xDir;
371            y += yDir;
372        }
373    }
374
375
376}
377
378/*------------------------------------------------------------------------------
379
380    Function: DecodeRasterScanMap
381
382        Functional description:
383            Function to decode raster scan slice group map type, i.e. slice
384            group map type 4.
385
386        Inputs:
387            map                               pointer to the map
388            sliceGroupChangeDirectionFlag     slice_group_change_direction_flag
389            sizeOfUpperLeftGroup              mbs in upperLeftGroup
390            picSize                           picture size in macroblocks
391
392        Outputs:
393            map                               slice group map is stored here
394
395        Returns:
396            none
397
398------------------------------------------------------------------------------*/
399
400void DecodeRasterScanMap(
401  u32 *map,
402  u32 sliceGroupChangeDirectionFlag,
403  u32 sizeOfUpperLeftGroup,
404  u32 picSize)
405{
406
407/* Variables */
408
409    u32 i;
410
411/* Code */
412
413    ASSERT(map);
414    ASSERT(picSize);
415    ASSERT(sizeOfUpperLeftGroup <= picSize);
416
417    for (i = 0; i < picSize; i++)
418        if (i < sizeOfUpperLeftGroup)
419            map[i] = (u32)sliceGroupChangeDirectionFlag;
420        else
421            map[i] = 1 - (u32)sliceGroupChangeDirectionFlag;
422
423
424}
425
426/*------------------------------------------------------------------------------
427
428    Function: DecodeWipeMap
429
430        Functional description:
431            Function to decode wipe slice group map type, i.e. slice group map
432            type 5.
433
434        Inputs:
435            sliceGroupChangeDirectionFlag     slice_group_change_direction_flag
436            sizeOfUpperLeftGroup              mbs in upperLeftGroup
437            picWidth                          picture width in macroblocks
438            picHeight                         picture height in macroblocks
439
440        Outputs:
441            map                               slice group map is stored here
442
443        Returns:
444            none
445
446------------------------------------------------------------------------------*/
447
448void DecodeWipeMap(
449  u32 *map,
450  u32 sliceGroupChangeDirectionFlag,
451  u32 sizeOfUpperLeftGroup,
452  u32 picWidth,
453  u32 picHeight)
454{
455
456/* Variables */
457
458    u32 i,j,k;
459
460/* Code */
461
462    ASSERT(map);
463    ASSERT(picWidth);
464    ASSERT(picHeight);
465    ASSERT(sizeOfUpperLeftGroup <= picWidth * picHeight);
466
467    k = 0;
468    for (j = 0; j < picWidth; j++)
469        for (i = 0; i < picHeight; i++)
470            if (k++ < sizeOfUpperLeftGroup)
471                map[ i * picWidth + j ] = (u32)sliceGroupChangeDirectionFlag;
472            else
473                map[ i * picWidth + j ] = 1 -
474                    (u32)sliceGroupChangeDirectionFlag;
475
476
477}
478
479/*------------------------------------------------------------------------------
480
481    Function: h264bsdDecodeSliceGroupMap
482
483        Functional description:
484            Function to decode macroblock to slice group map. Construction
485            of different slice group map types is handled by separate
486            functions defined above. See standard for details how slice group
487            maps are computed.
488
489        Inputs:
490            pps                     active picture parameter set
491            sliceGroupChangeCycle   slice_group_change_cycle
492            picWidth                picture width in macroblocks
493            picHeight               picture height in macroblocks
494
495        Outputs:
496            map                     slice group map is stored here
497
498        Returns:
499            none
500
501------------------------------------------------------------------------------*/
502
503void h264bsdDecodeSliceGroupMap(
504  u32 *map,
505  picParamSet_t *pps,
506  u32 sliceGroupChangeCycle,
507  u32 picWidth,
508  u32 picHeight)
509{
510
511/* Variables */
512
513    u32 i, picSize, unitsInSliceGroup0 = 0, sizeOfUpperLeftGroup = 0;
514
515/* Code */
516
517    ASSERT(map);
518    ASSERT(pps);
519    ASSERT(picWidth);
520    ASSERT(picHeight);
521    ASSERT(pps->sliceGroupMapType < 7);
522
523    picSize = picWidth * picHeight;
524
525    /* just one slice group -> all macroblocks belong to group 0 */
526    if (pps->numSliceGroups == 1)
527    {
528        H264SwDecMemset(map, 0, picSize * sizeof(u32));
529        return;
530    }
531
532    if (pps->sliceGroupMapType > 2 && pps->sliceGroupMapType < 6)
533    {
534        ASSERT(pps->sliceGroupChangeRate &&
535               pps->sliceGroupChangeRate <= picSize);
536
537        unitsInSliceGroup0 =
538            MIN(sliceGroupChangeCycle * pps->sliceGroupChangeRate, picSize);
539
540        if (pps->sliceGroupMapType == 4 || pps->sliceGroupMapType == 5)
541            sizeOfUpperLeftGroup = pps->sliceGroupChangeDirectionFlag ?
542                (picSize - unitsInSliceGroup0) : unitsInSliceGroup0;
543    }
544
545    switch (pps->sliceGroupMapType)
546    {
547        case 0:
548            DecodeInterleavedMap(map, pps->numSliceGroups,
549              pps->runLength, picSize);
550            break;
551
552        case 1:
553            DecodeDispersedMap(map, pps->numSliceGroups, picWidth,
554              picHeight);
555            break;
556
557        case 2:
558            DecodeForegroundLeftOverMap(map, pps->numSliceGroups,
559              pps->topLeft, pps->bottomRight, picWidth, picHeight);
560            break;
561
562        case 3:
563            DecodeBoxOutMap(map, pps->sliceGroupChangeDirectionFlag,
564              unitsInSliceGroup0, picWidth, picHeight);
565            break;
566
567        case 4:
568            DecodeRasterScanMap(map,
569              pps->sliceGroupChangeDirectionFlag, sizeOfUpperLeftGroup,
570              picSize);
571            break;
572
573        case 5:
574            DecodeWipeMap(map, pps->sliceGroupChangeDirectionFlag,
575              sizeOfUpperLeftGroup, picWidth, picHeight);
576            break;
577
578        default:
579            ASSERT(pps->sliceGroupId);
580            for (i = 0; i < picSize; i++)
581            {
582                ASSERT(pps->sliceGroupId[i] < pps->numSliceGroups);
583                map[i] = pps->sliceGroupId[i];
584            }
585            break;
586    }
587
588}
589
590