blob: 7cbb534155cc2b5cd8b7be8dcf9be49af211fe1d [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*------------------------------------------------------------------------------
Table of contents
1. Include headers
2. External compiler flags
3. Module defines
4. Local function prototypes
5. Functions
DecodeInterleavedMap
DecodeDispersedMap
DecodeForegroundLeftOverMap
DecodeBoxOutMap
DecodeRasterScanMap
DecodeWipeMap
h264bsdDecodeSliceGroupMap
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include "basetype.h"
#include "h264bsd_slice_group_map.h"
#include "h264bsd_cfg.h"
#include "h264bsd_pic_param_set.h"
#include "h264bsd_util.h"
/*------------------------------------------------------------------------------
2. External compiler flags
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
3. Module defines
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
4. Local function prototypes
------------------------------------------------------------------------------*/
static void DecodeInterleavedMap(
u32 *map,
u32 numSliceGroups,
u32 *runLength,
u32 picSize);
static void DecodeDispersedMap(
u32 *map,
u32 numSliceGroups,
u32 picWidth,
u32 picHeight);
static void DecodeForegroundLeftOverMap(
u32 *map,
u32 numSliceGroups,
u32 *topLeft,
u32 *bottomRight,
u32 picWidth,
u32 picHeight);
static void DecodeBoxOutMap(
u32 *map,
u32 sliceGroupChangeDirectionFlag,
u32 unitsInSliceGroup0,
u32 picWidth,
u32 picHeight);
static void DecodeRasterScanMap(
u32 *map,
u32 sliceGroupChangeDirectionFlag,
u32 sizeOfUpperLeftGroup,
u32 picSize);
static void DecodeWipeMap(
u32 *map,
u32 sliceGroupChangeDirectionFlag,
u32 sizeOfUpperLeftGroup,
u32 picWidth,
u32 picHeight);
/*------------------------------------------------------------------------------
Function: DecodeInterleavedMap
Functional description:
Function to decode interleaved slice group map type, i.e. slice
group map type 0.
Inputs:
map pointer to the map
numSliceGroups number of slice groups
runLength run_length[] values for each slice group
picSize picture size in macroblocks
Outputs:
map slice group map is stored here
Returns:
none
------------------------------------------------------------------------------*/
void DecodeInterleavedMap(
u32 *map,
u32 numSliceGroups,
u32 *runLength,
u32 picSize)
{
/* Variables */
u32 i,j, group;
/* Code */
ASSERT(map);
ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
ASSERT(runLength);
i = 0;
do {
for (group = 0; group < numSliceGroups && i < picSize;
i += runLength[group++])
{
ASSERT(runLength[group] <= picSize);
for (j = 0; j < runLength[group] && i + j < picSize; j++)
map[i+j] = group;
}
} while (i < picSize);
}
/*------------------------------------------------------------------------------
Function: DecodeDispersedMap
Functional description:
Function to decode dispersed slice group map type, i.e. slice
group map type 1.
Inputs:
map pointer to the map
numSliceGroups number of slice groups
picWidth picture width in macroblocks
picHeight picture height in macroblocks
Outputs:
map slice group map is stored here
Returns:
none
------------------------------------------------------------------------------*/
void DecodeDispersedMap(
u32 *map,
u32 numSliceGroups,
u32 picWidth,
u32 picHeight)
{
/* Variables */
u32 i, picSize;
/* Code */
ASSERT(map);
ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
ASSERT(picWidth);
ASSERT(picHeight);
picSize = picWidth * picHeight;
for (i = 0; i < picSize; i++)
map[i] = ((i % picWidth) + (((i / picWidth) * numSliceGroups) >> 1)) %
numSliceGroups;
}
/*------------------------------------------------------------------------------
Function: DecodeForegroundLeftOverMap
Functional description:
Function to decode foreground with left-over slice group map type,
i.e. slice group map type 2.
Inputs:
map pointer to the map
numSliceGroups number of slice groups
topLeft top_left[] values
bottomRight bottom_right[] values
picWidth picture width in macroblocks
picHeight picture height in macroblocks
Outputs:
map slice group map is stored here
Returns:
none
------------------------------------------------------------------------------*/
void DecodeForegroundLeftOverMap(
u32 *map,
u32 numSliceGroups,
u32 *topLeft,
u32 *bottomRight,
u32 picWidth,
u32 picHeight)
{
/* Variables */
u32 i,y,x,yTopLeft,yBottomRight,xTopLeft,xBottomRight, picSize;
u32 group;
/* Code */
ASSERT(map);
ASSERT(numSliceGroups >= 1 && numSliceGroups <= MAX_NUM_SLICE_GROUPS);
ASSERT(topLeft);
ASSERT(bottomRight);
ASSERT(picWidth);
ASSERT(picHeight);
picSize = picWidth * picHeight;
for (i = 0; i < picSize; i++)
map[i] = numSliceGroups - 1;
for (group = numSliceGroups - 1; group--; )
{
ASSERT( topLeft[group] <= bottomRight[group] &&
bottomRight[group] < picSize );
yTopLeft = topLeft[group] / picWidth;
xTopLeft = topLeft[group] % picWidth;
yBottomRight = bottomRight[group] / picWidth;
xBottomRight = bottomRight[group] % picWidth;
ASSERT(xTopLeft <= xBottomRight);
for (y = yTopLeft; y <= yBottomRight; y++)
for (x = xTopLeft; x <= xBottomRight; x++)
map[ y * picWidth + x ] = group;
}
}
/*------------------------------------------------------------------------------
Function: DecodeBoxOutMap
Functional description:
Function to decode box-out slice group map type, i.e. slice group
map type 3.
Inputs:
map pointer to the map
sliceGroupChangeDirectionFlag slice_group_change_direction_flag
unitsInSliceGroup0 mbs on slice group 0
picWidth picture width in macroblocks
picHeight picture height in macroblocks
Outputs:
map slice group map is stored here
Returns:
none
------------------------------------------------------------------------------*/
void DecodeBoxOutMap(
u32 *map,
u32 sliceGroupChangeDirectionFlag,
u32 unitsInSliceGroup0,
u32 picWidth,
u32 picHeight)
{
/* Variables */
u32 i, k, picSize;
i32 x, y, xDir, yDir, leftBound, topBound, rightBound, bottomBound;
u32 mapUnitVacant;
/* Code */
ASSERT(map);
ASSERT(picWidth);
ASSERT(picHeight);
picSize = picWidth * picHeight;
ASSERT(unitsInSliceGroup0 <= picSize);
for (i = 0; i < picSize; i++)
map[i] = 1;
x = (picWidth - (u32)sliceGroupChangeDirectionFlag) >> 1;
y = (picHeight - (u32)sliceGroupChangeDirectionFlag) >> 1;
leftBound = x;
topBound = y;
rightBound = x;
bottomBound = y;
xDir = (i32)sliceGroupChangeDirectionFlag - 1;
yDir = (i32)sliceGroupChangeDirectionFlag;
for (k = 0; k < unitsInSliceGroup0; k += mapUnitVacant ? 1 : 0)
{
mapUnitVacant = (map[ (u32)y * picWidth + (u32)x ] == 1) ?
HANTRO_TRUE : HANTRO_FALSE;
if (mapUnitVacant)
map[ (u32)y * picWidth + (u32)x ] = 0;
if (xDir == -1 && x == leftBound)
{
leftBound = MAX(leftBound - 1, 0);
x = leftBound;
xDir = 0;
yDir = 2 * (i32)sliceGroupChangeDirectionFlag - 1;
}
else if (xDir == 1 && x == rightBound)
{
rightBound = MIN(rightBound + 1, (i32)picWidth - 1);
x = rightBound;
xDir = 0;
yDir = 1 - 2 * (i32)sliceGroupChangeDirectionFlag;
}
else if (yDir == -1 && y == topBound)
{
topBound = MAX(topBound - 1, 0);
y = topBound;
xDir = 1 - 2 * (i32)sliceGroupChangeDirectionFlag;
yDir = 0;
}
else if (yDir == 1 && y == bottomBound)
{
bottomBound = MIN(bottomBound + 1, (i32)picHeight - 1);
y = bottomBound;
xDir = 2 * (i32)sliceGroupChangeDirectionFlag - 1;
yDir = 0;
}
else
{
x += xDir;
y += yDir;
}
}
}
/*------------------------------------------------------------------------------
Function: DecodeRasterScanMap
Functional description:
Function to decode raster scan slice group map type, i.e. slice
group map type 4.
Inputs:
map pointer to the map
sliceGroupChangeDirectionFlag slice_group_change_direction_flag
sizeOfUpperLeftGroup mbs in upperLeftGroup
picSize picture size in macroblocks
Outputs:
map slice group map is stored here
Returns:
none
------------------------------------------------------------------------------*/
void DecodeRasterScanMap(
u32 *map,
u32 sliceGroupChangeDirectionFlag,
u32 sizeOfUpperLeftGroup,
u32 picSize)
{
/* Variables */
u32 i;
/* Code */
ASSERT(map);
ASSERT(picSize);
ASSERT(sizeOfUpperLeftGroup <= picSize);
for (i = 0; i < picSize; i++)
if (i < sizeOfUpperLeftGroup)
map[i] = (u32)sliceGroupChangeDirectionFlag;
else
map[i] = 1 - (u32)sliceGroupChangeDirectionFlag;
}
/*------------------------------------------------------------------------------
Function: DecodeWipeMap
Functional description:
Function to decode wipe slice group map type, i.e. slice group map
type 5.
Inputs:
sliceGroupChangeDirectionFlag slice_group_change_direction_flag
sizeOfUpperLeftGroup mbs in upperLeftGroup
picWidth picture width in macroblocks
picHeight picture height in macroblocks
Outputs:
map slice group map is stored here
Returns:
none
------------------------------------------------------------------------------*/
void DecodeWipeMap(
u32 *map,
u32 sliceGroupChangeDirectionFlag,
u32 sizeOfUpperLeftGroup,
u32 picWidth,
u32 picHeight)
{
/* Variables */
u32 i,j,k;
/* Code */
ASSERT(map);
ASSERT(picWidth);
ASSERT(picHeight);
ASSERT(sizeOfUpperLeftGroup <= picWidth * picHeight);
k = 0;
for (j = 0; j < picWidth; j++)
for (i = 0; i < picHeight; i++)
if (k++ < sizeOfUpperLeftGroup)
map[ i * picWidth + j ] = (u32)sliceGroupChangeDirectionFlag;
else
map[ i * picWidth + j ] = 1 -
(u32)sliceGroupChangeDirectionFlag;
}
/*------------------------------------------------------------------------------
Function: h264bsdDecodeSliceGroupMap
Functional description:
Function to decode macroblock to slice group map. Construction
of different slice group map types is handled by separate
functions defined above. See standard for details how slice group
maps are computed.
Inputs:
pps active picture parameter set
sliceGroupChangeCycle slice_group_change_cycle
picWidth picture width in macroblocks
picHeight picture height in macroblocks
Outputs:
map slice group map is stored here
Returns:
none
------------------------------------------------------------------------------*/
void h264bsdDecodeSliceGroupMap(
u32 *map,
picParamSet_t *pps,
u32 sliceGroupChangeCycle,
u32 picWidth,
u32 picHeight)
{
/* Variables */
u32 i, picSize, unitsInSliceGroup0 = 0, sizeOfUpperLeftGroup = 0;
/* Code */
ASSERT(map);
ASSERT(pps);
ASSERT(picWidth);
ASSERT(picHeight);
ASSERT(pps->sliceGroupMapType < 7);
picSize = picWidth * picHeight;
/* just one slice group -> all macroblocks belong to group 0 */
if (pps->numSliceGroups == 1)
{
H264SwDecMemset(map, 0, picSize * sizeof(u32));
return;
}
if (pps->sliceGroupMapType > 2 && pps->sliceGroupMapType < 6)
{
ASSERT(pps->sliceGroupChangeRate &&
pps->sliceGroupChangeRate <= picSize);
unitsInSliceGroup0 =
MIN(sliceGroupChangeCycle * pps->sliceGroupChangeRate, picSize);
if (pps->sliceGroupMapType == 4 || pps->sliceGroupMapType == 5)
sizeOfUpperLeftGroup = pps->sliceGroupChangeDirectionFlag ?
(picSize - unitsInSliceGroup0) : unitsInSliceGroup0;
}
switch (pps->sliceGroupMapType)
{
case 0:
DecodeInterleavedMap(map, pps->numSliceGroups,
pps->runLength, picSize);
break;
case 1:
DecodeDispersedMap(map, pps->numSliceGroups, picWidth,
picHeight);
break;
case 2:
DecodeForegroundLeftOverMap(map, pps->numSliceGroups,
pps->topLeft, pps->bottomRight, picWidth, picHeight);
break;
case 3:
DecodeBoxOutMap(map, pps->sliceGroupChangeDirectionFlag,
unitsInSliceGroup0, picWidth, picHeight);
break;
case 4:
DecodeRasterScanMap(map,
pps->sliceGroupChangeDirectionFlag, sizeOfUpperLeftGroup,
picSize);
break;
case 5:
DecodeWipeMap(map, pps->sliceGroupChangeDirectionFlag,
sizeOfUpperLeftGroup, picWidth, picHeight);
break;
default:
ASSERT(pps->sliceGroupId);
for (i = 0; i < picSize; i++)
{
ASSERT(pps->sliceGroupId[i] < pps->numSliceGroups);
map[i] = pps->sliceGroupId[i];
}
break;
}
}