/* * 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; } }