package org.jcodec.codecs.h264.decode.aso; import static org.jcodec.codecs.h264.io.model.SeqParameterSet.getPicHeightInMbs; import org.jcodec.codecs.h264.io.model.PictureParameterSet; import org.jcodec.codecs.h264.io.model.SeqParameterSet; import org.jcodec.codecs.h264.io.model.SliceHeader; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * @author The JCodec project * */ public class MapManager { private SeqParameterSet sps; private PictureParameterSet pps; private MBToSliceGroupMap mbToSliceGroupMap; private int prevSliceGroupChangeCycle; public MapManager(SeqParameterSet sps, PictureParameterSet pps) { this.sps = sps; this.pps = pps; this.mbToSliceGroupMap = buildMap(sps, pps); } private MBToSliceGroupMap buildMap(SeqParameterSet sps, PictureParameterSet pps) { int numGroups = pps.num_slice_groups_minus1 + 1; if (numGroups > 1) { int[] map; int picWidthInMbs = sps.pic_width_in_mbs_minus1 + 1; int picHeightInMbs = SeqParameterSet.getPicHeightInMbs(sps); if (pps.slice_group_map_type == 0) { int[] runLength = new int[numGroups]; for (int i = 0; i < numGroups; i++) { runLength[i] = pps.run_length_minus1[i] + 1; } map = SliceGroupMapBuilder.buildInterleavedMap(picWidthInMbs, picHeightInMbs, runLength); } else if (pps.slice_group_map_type == 1) { map = SliceGroupMapBuilder.buildDispersedMap(picWidthInMbs, picHeightInMbs, numGroups); } else if (pps.slice_group_map_type == 2) { map = SliceGroupMapBuilder.buildForegroundMap(picWidthInMbs, picHeightInMbs, numGroups, pps.top_left, pps.bottom_right); } else if (pps.slice_group_map_type >= 3 && pps.slice_group_map_type <= 5) { return null; } else if (pps.slice_group_map_type == 6) { map = pps.slice_group_id; } else { throw new RuntimeException("Unsupported slice group map type"); } return buildMapIndices(map, numGroups); } return null; } private MBToSliceGroupMap buildMapIndices(int[] map, int numGroups) { int[] ind = new int[numGroups]; int[] indices = new int[map.length]; for (int i = 0; i < map.length; i++) { indices[i] = ind[map[i]]++; } int[][] inverse = new int[numGroups][]; for (int i = 0; i < numGroups; i++) { inverse[i] = new int[ind[i]]; } ind = new int[numGroups]; for (int i = 0; i < map.length; i++) { int sliceGroup = map[i]; inverse[sliceGroup][ind[sliceGroup]++] = i; } return new MBToSliceGroupMap(map, indices, inverse); } private void updateMap(SliceHeader sh) { int mapType = pps.slice_group_map_type; int numGroups = pps.num_slice_groups_minus1 + 1; if (numGroups > 1 && mapType >= 3 && mapType <= 5 && (sh.slice_group_change_cycle != prevSliceGroupChangeCycle || mbToSliceGroupMap == null)) { prevSliceGroupChangeCycle = sh.slice_group_change_cycle; int picWidthInMbs = sps.pic_width_in_mbs_minus1 + 1; int picHeightInMbs = SeqParameterSet.getPicHeightInMbs(sps); int picSizeInMapUnits = picWidthInMbs * picHeightInMbs; int mapUnitsInSliceGroup0 = sh.slice_group_change_cycle * (pps.slice_group_change_rate_minus1 + 1); mapUnitsInSliceGroup0 = mapUnitsInSliceGroup0 > picSizeInMapUnits ? picSizeInMapUnits : mapUnitsInSliceGroup0; int sizeOfUpperLeftGroup = (pps.slice_group_change_direction_flag ? (picSizeInMapUnits - mapUnitsInSliceGroup0) : mapUnitsInSliceGroup0); int[] map; if (mapType == 3) { map = SliceGroupMapBuilder.buildBoxOutMap(picWidthInMbs, picHeightInMbs, pps.slice_group_change_direction_flag, mapUnitsInSliceGroup0); } else if (mapType == 4) { map = SliceGroupMapBuilder.buildRasterScanMap(picWidthInMbs, picHeightInMbs, sizeOfUpperLeftGroup, pps.slice_group_change_direction_flag); } else { map = SliceGroupMapBuilder.buildWipeMap(picWidthInMbs, picHeightInMbs, sizeOfUpperLeftGroup, pps.slice_group_change_direction_flag); } this.mbToSliceGroupMap = buildMapIndices(map, numGroups); } } public Mapper getMapper(SliceHeader sh) { updateMap(sh); int firstMBInSlice = sh.first_mb_in_slice; if (pps.num_slice_groups_minus1 > 0) { return new PrebuiltMBlockMapper(mbToSliceGroupMap, firstMBInSlice, sps.pic_width_in_mbs_minus1 + 1); } else { return new FlatMBlockMapper(sps.pic_width_in_mbs_minus1 + 1, firstMBInSlice); } } }