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