blob: d66eba3045ab118f19a0ff4f0939f8c919fddcb3 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* 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.
* -------------------------------------------------------------------
*/
#include <string.h>
#include "avclib_common.h"
/* see subclause 8.2.2 Decoding process for macroblock to slice group map */
OSCL_EXPORT_REF AVCStatus FMOInit(AVCCommonObj *video)
{
AVCPicParamSet *currPPS = video->currPicParams;
int *MbToSliceGroupMap = video->MbToSliceGroupMap;
int PicSizeInMapUnits = video->PicSizeInMapUnits;
int PicWidthInMbs = video->PicWidthInMbs;
if (currPPS->num_slice_groups_minus1 == 0)
{
memset(video->MbToSliceGroupMap, 0, video->PicSizeInMapUnits*sizeof(uint));
}
else
{
switch (currPPS->slice_group_map_type)
{
case 0:
FmoGenerateType0MapUnitMap(MbToSliceGroupMap, currPPS->run_length_minus1, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
break;
case 1:
FmoGenerateType1MapUnitMap(MbToSliceGroupMap, PicWidthInMbs, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
break;
case 2:
FmoGenerateType2MapUnitMap(currPPS, MbToSliceGroupMap, PicWidthInMbs, currPPS->num_slice_groups_minus1, PicSizeInMapUnits);
break;
case 3:
FmoGenerateType3MapUnitMap(video, currPPS, MbToSliceGroupMap, PicWidthInMbs);
break;
case 4:
FmoGenerateType4MapUnitMap(MbToSliceGroupMap, video->MapUnitsInSliceGroup0, currPPS->slice_group_change_direction_flag, PicSizeInMapUnits);
break;
case 5:
FmoGenerateType5MapUnitMap(MbToSliceGroupMap, video, currPPS->slice_group_change_direction_flag, PicSizeInMapUnits);
break;
case 6:
FmoGenerateType6MapUnitMap(MbToSliceGroupMap, (int*)currPPS->slice_group_id, PicSizeInMapUnits);
break;
default:
return AVC_FAIL; /* out of range, shouldn't come this far */
}
}
return AVC_SUCCESS;
}
/* see subclause 8.2.2.1 interleaved slice group map type*/
void FmoGenerateType0MapUnitMap(int *mapUnitToSliceGroupMap, uint *run_length_minus1, uint num_slice_groups_minus1, uint PicSizeInMapUnits)
{
uint iGroup, j;
uint i = 0;
do
{
for (iGroup = 0;
(iGroup <= num_slice_groups_minus1) && (i < PicSizeInMapUnits);
i += run_length_minus1[iGroup++] + 1)
{
for (j = 0; j <= run_length_minus1[ iGroup ] && i + j < PicSizeInMapUnits; j++)
mapUnitToSliceGroupMap[i+j] = iGroup;
}
}
while (i < PicSizeInMapUnits);
}
/* see subclause 8.2.2.2 dispersed slice group map type*/
void FmoGenerateType1MapUnitMap(int *mapUnitToSliceGroupMap, int PicWidthInMbs, uint num_slice_groups_minus1, uint PicSizeInMapUnits)
{
uint i;
for (i = 0; i < PicSizeInMapUnits; i++)
{
mapUnitToSliceGroupMap[i] = ((i % PicWidthInMbs) + (((i / PicWidthInMbs) * (num_slice_groups_minus1 + 1)) / 2))
% (num_slice_groups_minus1 + 1);
}
}
/* see subclause 8.2.2.3 foreground with left-over slice group map type */
void FmoGenerateType2MapUnitMap(AVCPicParamSet *pps, int *mapUnitToSliceGroupMap, int PicWidthInMbs,
uint num_slice_groups_minus1, uint PicSizeInMapUnits)
{
int iGroup;
uint i, x, y;
uint yTopLeft, xTopLeft, yBottomRight, xBottomRight;
for (i = 0; i < PicSizeInMapUnits; i++)
{
mapUnitToSliceGroupMap[ i ] = num_slice_groups_minus1;
}
for (iGroup = num_slice_groups_minus1 - 1 ; iGroup >= 0; iGroup--)
{
yTopLeft = pps->top_left[ iGroup ] / PicWidthInMbs;
xTopLeft = pps->top_left[ iGroup ] % PicWidthInMbs;
yBottomRight = pps->bottom_right[ iGroup ] / PicWidthInMbs;
xBottomRight = pps->bottom_right[ iGroup ] % PicWidthInMbs;
for (y = yTopLeft; y <= yBottomRight; y++)
{
for (x = xTopLeft; x <= xBottomRight; x++)
{
mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] = iGroup;
}
}
}
}
/* see subclause 8.2.2.4 box-out slice group map type */
/* follow the text rather than the JM, it's quite different. */
void FmoGenerateType3MapUnitMap(AVCCommonObj *video, AVCPicParamSet* pps, int *mapUnitToSliceGroupMap,
int PicWidthInMbs)
{
uint i, k;
int leftBound, topBound, rightBound, bottomBound;
int x, y, xDir, yDir;
int mapUnitVacant;
uint PicSizeInMapUnits = video->PicSizeInMapUnits;
uint MapUnitsInSliceGroup0 = video->MapUnitsInSliceGroup0;
for (i = 0; i < PicSizeInMapUnits; i++)
{
mapUnitToSliceGroupMap[ i ] = 1;
}
x = (PicWidthInMbs - pps->slice_group_change_direction_flag) / 2;
y = (video->PicHeightInMapUnits - pps->slice_group_change_direction_flag) / 2;
leftBound = x;
topBound = y;
rightBound = x;
bottomBound = y;
xDir = pps->slice_group_change_direction_flag - 1;
yDir = pps->slice_group_change_direction_flag;
for (k = 0; k < MapUnitsInSliceGroup0; k += mapUnitVacant)
{
mapUnitVacant = (mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] == 1);
if (mapUnitVacant)
{
mapUnitToSliceGroupMap[ y * PicWidthInMbs + x ] = 0;
}
if (xDir == -1 && x == leftBound)
{
leftBound = AVC_MAX(leftBound - 1, 0);
x = leftBound;
xDir = 0;
yDir = 2 * pps->slice_group_change_direction_flag - 1;
}
else if (xDir == 1 && x == rightBound)
{
rightBound = AVC_MIN(rightBound + 1, (int)PicWidthInMbs - 1);
x = rightBound;
xDir = 0;
yDir = 1 - 2 * pps->slice_group_change_direction_flag;
}
else if (yDir == -1 && y == topBound)
{
topBound = AVC_MAX(topBound - 1, 0);
y = topBound;
xDir = 1 - 2 * pps->slice_group_change_direction_flag;
yDir = 0;
}
else if (yDir == 1 && y == bottomBound)
{
bottomBound = AVC_MIN(bottomBound + 1, (int)video->PicHeightInMapUnits - 1);
y = bottomBound;
xDir = 2 * pps->slice_group_change_direction_flag - 1;
yDir = 0;
}
else
{
x = x + xDir;
y = y + yDir;
}
}
}
/* see subclause 8.2.2.5 raster scan slice group map types */
void FmoGenerateType4MapUnitMap(int *mapUnitToSliceGroupMap, int MapUnitsInSliceGroup0, int slice_group_change_direction_flag, uint PicSizeInMapUnits)
{
uint sizeOfUpperLeftGroup = slice_group_change_direction_flag ? (PicSizeInMapUnits - MapUnitsInSliceGroup0) : MapUnitsInSliceGroup0;
uint i;
for (i = 0; i < PicSizeInMapUnits; i++)
if (i < sizeOfUpperLeftGroup)
mapUnitToSliceGroupMap[ i ] = 1 - slice_group_change_direction_flag;
else
mapUnitToSliceGroupMap[ i ] = slice_group_change_direction_flag;
}
/* see subclause 8.2.2.6, wipe slice group map type. */
void FmoGenerateType5MapUnitMap(int *mapUnitToSliceGroupMap, AVCCommonObj *video,
int slice_group_change_direction_flag, uint PicSizeInMapUnits)
{
int PicWidthInMbs = video->PicWidthInMbs;
int PicHeightInMapUnits = video->PicHeightInMapUnits;
int MapUnitsInSliceGroup0 = video->MapUnitsInSliceGroup0;
int sizeOfUpperLeftGroup = slice_group_change_direction_flag ? (PicSizeInMapUnits - MapUnitsInSliceGroup0) : MapUnitsInSliceGroup0;
int i, j, k = 0;
for (j = 0; j < PicWidthInMbs; j++)
{
for (i = 0; i < PicHeightInMapUnits; i++)
{
if (k++ < sizeOfUpperLeftGroup)
{
mapUnitToSliceGroupMap[ i * PicWidthInMbs + j ] = 1 - slice_group_change_direction_flag;
}
else
{
mapUnitToSliceGroupMap[ i * PicWidthInMbs + j ] = slice_group_change_direction_flag;
}
}
}
}
/* see subclause 8.2.2.7, explicit slice group map */
void FmoGenerateType6MapUnitMap(int *mapUnitToSliceGroupMap, int *slice_group_id, uint PicSizeInMapUnits)
{
uint i;
for (i = 0; i < PicSizeInMapUnits; i++)
{
mapUnitToSliceGroupMap[i] = slice_group_id[i];
}
}