src/main/java/org/jcodec/codecs/h264/decode/aso/SliceGroupMapBuilder.java
public static int[] buildBoxOutMap(int picWidthInMbs, int picHeightInMbs, boolean changeDirection,
            int numberOfMbsInBox) {

        int picSizeInMbs = picWidthInMbs * picHeightInMbs;
        int[] groups = new int[picSizeInMbs];
        int changeDirectionInt = changeDirection ? 1 : 0;

        for (int i = 0; i < picSizeInMbs; i++)
            groups[i] = 1;

        int x = (picWidthInMbs - changeDirectionInt) / 2;
        int y = (picHeightInMbs - changeDirectionInt) / 2;
        int leftBound = x;
        int topBound = y;
        int rightBound = x;
        int bottomBound = y;
        int xDir = changeDirectionInt - 1;
        int yDir = changeDirectionInt;

        boolean mapUnitVacant = false;
        for (int k = 0; k < numberOfMbsInBox; k += (mapUnitVacant ? 1 : 0)) {
            int mbAddr = y * picWidthInMbs + x;
            mapUnitVacant = (groups[mbAddr] == 1);
            if (mapUnitVacant) {
                groups[mbAddr] = 0;
            }
            if (xDir == -1 && x == leftBound) {
                leftBound = Max(leftBound - 1, 0);
                x = leftBound;
                xDir = 0;
                yDir = 2 * changeDirectionInt - 1;
            } else if (xDir == 1 && x == rightBound) {
                rightBound = Min(rightBound + 1, picWidthInMbs - 1);
                x = rightBound;
                xDir = 0;
                yDir = 1 - 2 * changeDirectionInt;
            } else if (yDir == -1 && y == topBound) {
                topBound = Max(topBound - 1, 0);
                y = topBound;
                xDir = 1 - 2 * changeDirectionInt;
                yDir = 0;
            } else if (yDir == 1 && y == bottomBound) {
                bottomBound = Min(bottomBound + 1, picHeightInMbs - 1);
                y = bottomBound;
                xDir = 2 * changeDirectionInt - 1;
                yDir = 0;
            } else {
                x += xDir;
                y += yDir;
            }
        }

        return groups;
    }
public static int[] buildBoxOutMap(int picWidthInMbs, int picHeightInMbs, boolean changeDirection,
            int numberOfMbsInBox) {

        int picSizeInMbs = picWidthInMbs * picHeightInMbs;
        int[] groups = new int[picSizeInMbs];
        int changeDirectionInt = changeDirection ? 1 : 0;

        for (int i = 0; i < picSizeInMbs; i++)
            groups[i] = 1;

        int x = (picWidthInMbs - changeDirectionInt) / 2;
        int y = (picHeightInMbs - changeDirectionInt) / 2;
        int leftBound = x;
        int topBound = y;
        int rightBound = x;
        int bottomBound = y;
        int xDir = changeDirectionInt - 1;
        int yDir = changeDirectionInt;

        boolean mapUnitVacant = false;
        for (int k = 0; k < numberOfMbsInBox; k += (mapUnitVacant ? 1 : 0)) {
            int mbAddr = y * picWidthInMbs + x;
            mapUnitVacant = (groups[mbAddr] == 1);
            if (mapUnitVacant) {
                groups[mbAddr] = 0;
            }
            if (xDir == -1 && x == leftBound) {
                leftBound = Max(leftBound - 1, 0);
                x = leftBound;
                xDir = 0;
                yDir = 2 * changeDirectionInt - 1;
            } else if (xDir == 1 && x == rightBound) {
                rightBound = Min(rightBound + 1, picWidthInMbs - 1);
                x = rightBound;
                xDir = 0;
                yDir = 1 - 2 * changeDirectionInt;
            } else if (yDir == -1 && y == topBound) {
                topBound = Max(topBound - 1, 0);
                y = topBound;
                xDir = 1 - 2 * changeDirectionInt;
                yDir = 0;
            } else if (yDir == 1 && y == bottomBound) {
                bottomBound = Min(bottomBound + 1, picHeightInMbs - 1);
                y = bottomBound;
                xDir = 2 * changeDirectionInt - 1;
                yDir = 0;
            } else {
                x += xDir;
                y += yDir;
            }
        }

        return groups;
    }
public static int [ ] buildBoxOutMap ( int picWidthInMbs , int picHeightInMbs , boolean changeDirection , int numberOfMbsInBox ) { int picSizeInMbs = picWidthInMbs * picHeightInMbs ; int [ ] groups = new int [ picSizeInMbs ] ; int changeDirectionInt = changeDirection ? 1 : 0 ; for ( int i = 0 ; i < picSizeInMbs ; i ++ ) groups [ i ] = 1 ; int x = ( picWidthInMbs - changeDirectionInt ) / 2 ; int y = ( picHeightInMbs - changeDirectionInt ) / 2 ; int leftBound = x ; int topBound = y ; int rightBound = x ; int bottomBound = y ; int xDir = changeDirectionInt - 1 ; int yDir = changeDirectionInt ; boolean mapUnitVacant = false ; for ( int k = 0 ; k < numberOfMbsInBox ; k += ( mapUnitVacant ? 1 : 0 ) ) { int mbAddr = y * picWidthInMbs + x ; mapUnitVacant = ( groups [ mbAddr ] == 1 ) ; if ( mapUnitVacant ) { groups [ mbAddr ] = 0 ; } if ( xDir == - 1 && x == leftBound ) { leftBound = Max ( leftBound - 1 , 0 ) ; x = leftBound ; xDir = 0 ; yDir = 2 * changeDirectionInt - 1 ; } else if ( xDir == 1 && x == rightBound ) { rightBound = Min ( rightBound + 1 , picWidthInMbs - 1 ) ; x = rightBound ; xDir = 0 ; yDir = 1 - 2 * changeDirectionInt ; } else if ( yDir == - 1 && y == topBound ) { topBound = Max ( topBound - 1 , 0 ) ; y = topBound ; xDir = 1 - 2 * changeDirectionInt ; yDir = 0 ; } else if ( yDir == 1 && y == bottomBound ) { bottomBound = Min ( bottomBound + 1 , picHeightInMbs - 1 ) ; y = bottomBound ; xDir = 2 * changeDirectionInt - 1 ; yDir = 0 ; } else { x += xDir ; y += yDir ; } } return groups ; }
A boxout macroblock to slice group mapping. Only applicable when there's
exactly 2 slice groups. Slice group 1 is a background, while slice group
0 is a box in the middle of the frame.

@param picWidthInMbs
@param picHeightInMbs
@param changeDirection
@param numberOfMbsInBox
number of macroblocks in slice group 0
@return
A boxout macroblock to slice group mapping . Only applicable when there s exactly 2 slice groups . Slice group 1 is a background while slice group 0 is a box in the middle of the frame .