1 /* 2 * Copyright 2012 castLabs, Berlin 3 * 4 * Licensed under the Apache License, Version 2.0 (the License); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an AS IS BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.googlecode.mp4parser.boxes.mp4.samplegrouping; 18 19 import com.coremedia.iso.IsoTypeReader; 20 import com.coremedia.iso.IsoTypeWriter; 21 import com.googlecode.mp4parser.AbstractFullBox; 22 23 import java.nio.ByteBuffer; 24 import java.util.LinkedList; 25 import java.util.List; 26 27 import static com.googlecode.mp4parser.util.CastUtils.l2i; 28 29 /** 30 * This table can be used to find the group that a sample belongs to and the associated description of that 31 * sample group. The table is compactly coded with each entry giving the index of the first sample of a run of 32 * samples with the same sample group descriptor. The sample group description ID is an index that refers to a 33 * SampleGroupDescription box, which contains entries describing the characteristics of each sample group. 34 * <p/> 35 * There may be multiple instances of this box if there is more than one sample grouping for the samples in a 36 * track. Each instance of the SampleToGroup box has a type code that distinguishes different sample 37 * groupings. Within a track, there shall be at most one instance of this box with a particular grouping type. The 38 * associated SampleGroupDescription shall indicate the same value for the grouping type. 39 * <p/> 40 * Version 1 of this box should only be used if a grouping type parameter is needed. 41 */ 42 public class SampleToGroupBox extends AbstractFullBox { 43 public static final String TYPE = "sbgp"; 44 45 46 private String groupingType; 47 private String groupingTypeParameter; 48 49 List<Entry> entries = new LinkedList<Entry>(); 50 SampleToGroupBox()51 public SampleToGroupBox() { 52 super(TYPE); 53 54 } 55 56 @Override getContentSize()57 protected long getContentSize() { 58 return this.getVersion() == 1 ? entries.size() * 8 + 16 : entries.size() * 8 + 12; 59 } 60 61 @Override getContent(ByteBuffer byteBuffer)62 protected void getContent(ByteBuffer byteBuffer) { 63 writeVersionAndFlags(byteBuffer); 64 byteBuffer.put(groupingType.getBytes()); 65 if (this.getVersion() == 1) { 66 byteBuffer.put(groupingTypeParameter.getBytes()); 67 } 68 IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); 69 for (Entry entry : entries) { 70 IsoTypeWriter.writeUInt32(byteBuffer, entry.getSampleCount()); 71 IsoTypeWriter.writeUInt32(byteBuffer, entry.getGroupDescriptionIndex()); 72 } 73 74 } 75 76 @Override _parseDetails(ByteBuffer content)77 protected void _parseDetails(ByteBuffer content) { 78 parseVersionAndFlags(content); 79 groupingType = IsoTypeReader.read4cc(content); 80 if (this.getVersion() == 1) { 81 groupingTypeParameter = IsoTypeReader.read4cc(content); 82 } 83 long entryCount = IsoTypeReader.readUInt32(content); 84 while (entryCount-- > 0) { 85 entries.add(new Entry(l2i(IsoTypeReader.readUInt32(content)), l2i(IsoTypeReader.readUInt32(content)))); 86 } 87 } 88 89 public static class Entry { 90 private long sampleCount; 91 private int groupDescriptionIndex; 92 Entry(long sampleCount, int groupDescriptionIndex)93 public Entry(long sampleCount, int groupDescriptionIndex) { 94 this.sampleCount = sampleCount; 95 this.groupDescriptionIndex = groupDescriptionIndex; 96 } 97 getSampleCount()98 public long getSampleCount() { 99 return sampleCount; 100 } 101 setSampleCount(long sampleCount)102 public void setSampleCount(long sampleCount) { 103 this.sampleCount = sampleCount; 104 } 105 getGroupDescriptionIndex()106 public int getGroupDescriptionIndex() { 107 return groupDescriptionIndex; 108 } 109 setGroupDescriptionIndex(int groupDescriptionIndex)110 public void setGroupDescriptionIndex(int groupDescriptionIndex) { 111 this.groupDescriptionIndex = groupDescriptionIndex; 112 } 113 114 @Override toString()115 public String toString() { 116 return "Entry{" + 117 "sampleCount=" + sampleCount + 118 ", groupDescriptionIndex=" + groupDescriptionIndex + 119 '}'; 120 } 121 122 @Override equals(Object o)123 public boolean equals(Object o) { 124 if (this == o) { 125 return true; 126 } 127 if (o == null || getClass() != o.getClass()) { 128 return false; 129 } 130 131 Entry entry = (Entry) o; 132 133 if (groupDescriptionIndex != entry.groupDescriptionIndex) { 134 return false; 135 } 136 if (sampleCount != entry.sampleCount) { 137 return false; 138 } 139 140 return true; 141 } 142 143 @Override hashCode()144 public int hashCode() { 145 int result = (int) (sampleCount ^ (sampleCount >>> 32)); 146 result = 31 * result + groupDescriptionIndex; 147 return result; 148 } 149 } 150 getGroupingType()151 public String getGroupingType() { 152 return groupingType; 153 } 154 setGroupingType(String groupingType)155 public void setGroupingType(String groupingType) { 156 this.groupingType = groupingType; 157 } 158 getGroupingTypeParameter()159 public String getGroupingTypeParameter() { 160 return groupingTypeParameter; 161 } 162 setGroupingTypeParameter(String groupingTypeParameter)163 public void setGroupingTypeParameter(String groupingTypeParameter) { 164 this.groupingTypeParameter = groupingTypeParameter; 165 } 166 getEntries()167 public List<Entry> getEntries() { 168 return entries; 169 } 170 setEntries(List<Entry> entries)171 public void setEntries(List<Entry> entries) { 172 this.entries = entries; 173 } 174 } 175