1 package com.googlecode.mp4parser.boxes.threegpp26244;
2 
3 import com.coremedia.iso.IsoTypeReader;
4 import com.coremedia.iso.IsoTypeWriter;
5 import com.googlecode.mp4parser.AbstractFullBox;
6 import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitReaderBuffer;
7 import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.BitWriterBuffer;
8 
9 import java.nio.ByteBuffer;
10 import java.util.ArrayList;
11 import java.util.List;
12 
13 /**
14  * <pre>
15  * aligned(8) class SegmentIndexBox extends FullBox(‘sidx’, version, 0) {
16  *  unsigned int(32) reference_ID;
17  *  unsigned int(32) timescale;
18  *  if (version==0)
19  *  {
20  *   unsigned int(32) earliest_presentation_time;
21  *   unsigned int(32) first_offset;
22  *  }
23  *  else
24  *  {
25  *   unsigned int(64) earliest_presentation_time;
26  *   unsigned int(64) first_offset;
27  *  }
28  *  unsigned int(16) reserved = 0;
29  *  unsigned int(16) reference_count;
30  *  for(i=1; i <= reference_count; i++)
31  *  {
32  *   bit (1)            reference_type;
33  *   unsigned int(31)   referenced_size;
34  *   unsigned int(32)   subsegment_duration;
35  *   bit(1)             starts_with_SAP;
36  *   unsigned int(3)    SAP_type;
37  *   unsigned int(28)   SAP_delta_time;
38  *  }
39  * }
40  * </pre>
41  */
42 public class SegmentIndexBox extends AbstractFullBox {
43     public static final String TYPE = "sidx";
44     List<Entry> entries = new ArrayList<Entry>();
45 
46     long referenceId;
47     long timeScale;
48     long earliestPresentationTime;
49     long firstOffset;
50     int reserved;
51 
52 
SegmentIndexBox()53     public SegmentIndexBox() {
54         super(TYPE);
55     }
56 
57     @Override
getContentSize()58     protected long getContentSize() {
59         long size = 4;
60         size += 4;
61         size += 4;
62         size += getVersion() == 0 ? 8 : 16;
63         size += 2; // reserved
64         size += 2; // reference count
65 
66         size += entries.size() * 12;
67 
68         return size;
69     }
70 
71     @Override
getContent(ByteBuffer byteBuffer)72     protected void getContent(ByteBuffer byteBuffer) {
73         writeVersionAndFlags(byteBuffer);
74         IsoTypeWriter.writeUInt32(byteBuffer, referenceId);
75         IsoTypeWriter.writeUInt32(byteBuffer, timeScale);
76         if (getVersion() == 0) {
77             IsoTypeWriter.writeUInt32(byteBuffer, earliestPresentationTime);
78             IsoTypeWriter.writeUInt32(byteBuffer, firstOffset);
79         } else {
80             IsoTypeWriter.writeUInt64(byteBuffer, earliestPresentationTime);
81             IsoTypeWriter.writeUInt64(byteBuffer, firstOffset);
82         }
83         IsoTypeWriter.writeUInt16(byteBuffer, reserved);
84         IsoTypeWriter.writeUInt16(byteBuffer, entries.size());
85         for (Entry entry : entries) {
86             BitWriterBuffer b = new BitWriterBuffer(byteBuffer);
87             b.writeBits(entry.getReferenceType(), 1);
88             b.writeBits(entry.getReferencedSize(), 31);
89             IsoTypeWriter.writeUInt32(byteBuffer, entry.getSubsegmentDuration());
90             b = new BitWriterBuffer(byteBuffer);
91             b.writeBits(entry.getStartsWithSap(), 1);
92             b.writeBits(entry.getSapType(), 3);
93             b.writeBits(entry.getSapDeltaTime(), 28);
94         }
95 
96     }
97 
98     @Override
_parseDetails(ByteBuffer content)99     protected void _parseDetails(ByteBuffer content) {
100         parseVersionAndFlags(content);
101         referenceId = IsoTypeReader.readUInt32(content);
102         timeScale = IsoTypeReader.readUInt32(content);
103         if (getVersion() == 0) {
104             earliestPresentationTime = IsoTypeReader.readUInt32(content);
105             firstOffset = IsoTypeReader.readUInt32(content);
106         } else {
107             earliestPresentationTime = IsoTypeReader.readUInt64(content);
108             firstOffset = IsoTypeReader.readUInt64(content);
109         }
110         reserved = IsoTypeReader.readUInt16(content);
111         int numEntries = IsoTypeReader.readUInt16(content);
112         for (int i = 0; i < numEntries; i++) {
113             BitReaderBuffer b = new BitReaderBuffer(content);
114             Entry e = new Entry();
115             e.setReferenceType((byte) b.readBits(1));
116             e.setReferencedSize(b.readBits(31));
117             e.setSubsegmentDuration(IsoTypeReader.readUInt32(content));
118             b = new BitReaderBuffer(content);
119             e.setStartsWithSap((byte) b.readBits(1));
120             e.setSapType((byte) b.readBits(3));
121             e.setSapDeltaTime(b.readBits(28));
122             entries.add(e);
123         }
124     }
125 
126 
getEntries()127     public List<Entry> getEntries() {
128         return entries;
129     }
130 
setEntries(List<Entry> entries)131     public void setEntries(List<Entry> entries) {
132         this.entries = entries;
133     }
134 
getReferenceId()135     public long getReferenceId() {
136         return referenceId;
137     }
138 
setReferenceId(long referenceId)139     public void setReferenceId(long referenceId) {
140         this.referenceId = referenceId;
141     }
142 
getTimeScale()143     public long getTimeScale() {
144         return timeScale;
145     }
146 
setTimeScale(long timeScale)147     public void setTimeScale(long timeScale) {
148         this.timeScale = timeScale;
149     }
150 
getEarliestPresentationTime()151     public long getEarliestPresentationTime() {
152         return earliestPresentationTime;
153     }
154 
setEarliestPresentationTime(long earliestPresentationTime)155     public void setEarliestPresentationTime(long earliestPresentationTime) {
156         this.earliestPresentationTime = earliestPresentationTime;
157     }
158 
getFirstOffset()159     public long getFirstOffset() {
160         return firstOffset;
161     }
162 
setFirstOffset(long firstOffset)163     public void setFirstOffset(long firstOffset) {
164         this.firstOffset = firstOffset;
165     }
166 
getReserved()167     public int getReserved() {
168         return reserved;
169     }
170 
setReserved(int reserved)171     public void setReserved(int reserved) {
172         this.reserved = reserved;
173     }
174 
175     public static class Entry {
176         byte referenceType;
177         int referencedSize;
178         long subsegmentDuration;
179         byte startsWithSap;
180         byte sapType;
181         int sapDeltaTime;
182 
Entry()183         public Entry() {
184         }
185 
Entry(byte referenceType, int referencedSize, long subsegmentDuration, byte startsWithSap, byte sapType, int sapDeltaTime)186         public Entry(byte referenceType, int referencedSize, long subsegmentDuration, byte startsWithSap, byte sapType, int sapDeltaTime) {
187             this.referenceType = referenceType;
188             this.referencedSize = referencedSize;
189             this.subsegmentDuration = subsegmentDuration;
190             this.startsWithSap = startsWithSap;
191             this.sapType = sapType;
192             this.sapDeltaTime = sapDeltaTime;
193         }
194 
getReferenceType()195         public byte getReferenceType() {
196             return referenceType;
197         }
198 
setReferenceType(byte referenceType)199         public void setReferenceType(byte referenceType) {
200             this.referenceType = referenceType;
201         }
202 
getReferencedSize()203         public int getReferencedSize() {
204             return referencedSize;
205         }
206 
setReferencedSize(int referencedSize)207         public void setReferencedSize(int referencedSize) {
208             this.referencedSize = referencedSize;
209         }
210 
getSubsegmentDuration()211         public long getSubsegmentDuration() {
212             return subsegmentDuration;
213         }
214 
setSubsegmentDuration(long subsegmentDuration)215         public void setSubsegmentDuration(long subsegmentDuration) {
216             this.subsegmentDuration = subsegmentDuration;
217         }
218 
getStartsWithSap()219         public byte getStartsWithSap() {
220             return startsWithSap;
221         }
222 
setStartsWithSap(byte startsWithSap)223         public void setStartsWithSap(byte startsWithSap) {
224             this.startsWithSap = startsWithSap;
225         }
226 
getSapType()227         public byte getSapType() {
228             return sapType;
229         }
230 
setSapType(byte sapType)231         public void setSapType(byte sapType) {
232             this.sapType = sapType;
233         }
234 
getSapDeltaTime()235         public int getSapDeltaTime() {
236             return sapDeltaTime;
237         }
238 
setSapDeltaTime(int sapDeltaTime)239         public void setSapDeltaTime(int sapDeltaTime) {
240             this.sapDeltaTime = sapDeltaTime;
241         }
242 
243         @Override
toString()244         public String toString() {
245             return "Entry{" +
246                     "referenceType=" + referenceType +
247                     ", referencedSize=" + referencedSize +
248                     ", subsegmentDuration=" + subsegmentDuration +
249                     ", startsWithSap=" + startsWithSap +
250                     ", sapType=" + sapType +
251                     ", sapDeltaTime=" + sapDeltaTime +
252                     '}';
253         }
254 
255         @Override
equals(Object o)256         public boolean equals(Object o) {
257             if (this == o) return true;
258             if (o == null || getClass() != o.getClass()) return false;
259 
260             Entry entry = (Entry) o;
261 
262             if (referenceType != entry.referenceType) return false;
263             if (referencedSize != entry.referencedSize) return false;
264             if (sapDeltaTime != entry.sapDeltaTime) return false;
265             if (sapType != entry.sapType) return false;
266             if (startsWithSap != entry.startsWithSap) return false;
267             if (subsegmentDuration != entry.subsegmentDuration) return false;
268 
269             return true;
270         }
271 
272         @Override
hashCode()273         public int hashCode() {
274             int result = (int) referenceType;
275             result = 31 * result + referencedSize;
276             result = 31 * result + (int) (subsegmentDuration ^ (subsegmentDuration >>> 32));
277             result = 31 * result + (int) startsWithSap;
278             result = 31 * result + (int) sapType;
279             result = 31 * result + sapDeltaTime;
280             return result;
281         }
282     }
283 }
284