package com.coremedia.iso.boxes; import com.coremedia.iso.IsoTypeReader; import com.coremedia.iso.IsoTypeWriter; import com.googlecode.mp4parser.AbstractFullBox; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import static com.googlecode.mp4parser.util.CastUtils.l2i; /** * aligned(8) class SubSampleInformationBox * extends FullBox('subs', version, 0) { * unsigned int(32) entry_count; * int i,j; * for (i=0; i < entry_count; i++) { * unsigned int(32) sample_delta; * unsigned int(16) subsample_count; * if (subsample_count > 0) { * for (j=0; j < subsample_count; j++) { * if(version == 1) * { * unsigned int(32) subsample_size; * } * else * { * unsigned int(16) subsample_size; * } * unsigned int(8) subsample_priority; * unsigned int(8) discardable; * unsigned int(32) reserved = 0; * } * } * } * } */ public class SubSampleInformationBox extends AbstractFullBox { public static final String TYPE = "subs"; private long entryCount; private List<SampleEntry> entries = new ArrayList<SampleEntry>(); public SubSampleInformationBox() { super(TYPE); } public List<SampleEntry> getEntries() { return entries; } public void setEntries(List<SampleEntry> entries) { this.entries = entries; entryCount = entries.size(); } @Override protected long getContentSize() { long entries = 8 + ((4 + 2) * entryCount); int subsampleEntries = 0; for (SampleEntry sampleEntry : this.entries) { subsampleEntries += sampleEntry.getSubsampleCount() * (((getVersion() == 1) ? 4 : 2) + 1 + 1 + 4); } return entries + subsampleEntries; } @Override public void _parseDetails(ByteBuffer content) { parseVersionAndFlags(content); entryCount = IsoTypeReader.readUInt32(content); for (int i = 0; i < entryCount; i++) { SampleEntry sampleEntry = new SampleEntry(); sampleEntry.setSampleDelta(IsoTypeReader.readUInt32(content)); int subsampleCount = IsoTypeReader.readUInt16(content); for (int j = 0; j < subsampleCount; j++) { SampleEntry.SubsampleEntry subsampleEntry = new SampleEntry.SubsampleEntry(); subsampleEntry.setSubsampleSize(getVersion() == 1 ? IsoTypeReader.readUInt32(content) : IsoTypeReader.readUInt16(content)); subsampleEntry.setSubsamplePriority(IsoTypeReader.readUInt8(content)); subsampleEntry.setDiscardable(IsoTypeReader.readUInt8(content)); subsampleEntry.setReserved(IsoTypeReader.readUInt32(content)); sampleEntry.addSubsampleEntry(subsampleEntry); } entries.add(sampleEntry); } } @Override protected void getContent(ByteBuffer byteBuffer) { writeVersionAndFlags(byteBuffer); IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); for (SampleEntry sampleEntry : entries) { IsoTypeWriter.writeUInt32(byteBuffer, sampleEntry.getSampleDelta()); IsoTypeWriter.writeUInt16(byteBuffer, sampleEntry.getSubsampleCount()); List<SampleEntry.SubsampleEntry> subsampleEntries = sampleEntry.getSubsampleEntries(); for (SampleEntry.SubsampleEntry subsampleEntry : subsampleEntries) { if (getVersion() == 1) { IsoTypeWriter.writeUInt32(byteBuffer, subsampleEntry.getSubsampleSize()); } else { IsoTypeWriter.writeUInt16(byteBuffer, l2i(subsampleEntry.getSubsampleSize())); } IsoTypeWriter.writeUInt8(byteBuffer, subsampleEntry.getSubsamplePriority()); IsoTypeWriter.writeUInt8(byteBuffer, subsampleEntry.getDiscardable()); IsoTypeWriter.writeUInt32(byteBuffer, subsampleEntry.getReserved()); } } } @Override public String toString() { return "SubSampleInformationBox{" + "entryCount=" + entryCount + ", entries=" + entries + '}'; } public static class SampleEntry { private long sampleDelta; private int subsampleCount; private List<SubsampleEntry> subsampleEntries = new ArrayList<SubsampleEntry>(); public long getSampleDelta() { return sampleDelta; } public void setSampleDelta(long sampleDelta) { this.sampleDelta = sampleDelta; } public int getSubsampleCount() { return subsampleCount; } public void setSubsampleCount(int subsampleCount) { this.subsampleCount = subsampleCount; } public List<SubsampleEntry> getSubsampleEntries() { return subsampleEntries; } public void addSubsampleEntry(SubsampleEntry subsampleEntry) { subsampleEntries.add(subsampleEntry); subsampleCount++; } public static class SubsampleEntry { private long subsampleSize; private int subsamplePriority; private int discardable; private long reserved; public long getSubsampleSize() { return subsampleSize; } public void setSubsampleSize(long subsampleSize) { this.subsampleSize = subsampleSize; } public int getSubsamplePriority() { return subsamplePriority; } public void setSubsamplePriority(int subsamplePriority) { this.subsamplePriority = subsamplePriority; } public int getDiscardable() { return discardable; } public void setDiscardable(int discardable) { this.discardable = discardable; } public long getReserved() { return reserved; } public void setReserved(long reserved) { this.reserved = reserved; } @Override public String toString() { return "SubsampleEntry{" + "subsampleSize=" + subsampleSize + ", subsamplePriority=" + subsamplePriority + ", discardable=" + discardable + ", reserved=" + reserved + '}'; } } @Override public String toString() { return "SampleEntry{" + "sampleDelta=" + sampleDelta + ", subsampleCount=" + subsampleCount + ", subsampleEntries=" + subsampleEntries + '}'; } } }