package org.mp4parser.boxes.iso14496.part12; import org.mp4parser.support.AbstractFullBox; import org.mp4parser.tools.CastUtils; import org.mp4parser.tools.IsoTypeReader; import org.mp4parser.tools.IsoTypeWriter; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; /** * <h1>4cc = "{@value #TYPE}"</h1> * <pre> * 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; * } * } * } * } * </pre> */ public class SubSampleInformationBox extends AbstractFullBox { public static final String TYPE = "subs"; private List<SubSampleEntry> entries = new ArrayList<SubSampleEntry>(); public SubSampleInformationBox() { super(TYPE); } public List<SubSampleEntry> getEntries() { return entries; } public void setEntries(List<SubSampleEntry> entries) { this.entries = entries; } @Override protected long getContentSize() { long size = 8; for (SubSampleEntry entry : entries) { size += 4; size += 2; for (int j = 0; j < entry.getSubsampleEntries().size(); j++) { if (getVersion() == 1) { size += 4; } else { size += 2; } size += 2; size += 4; } } return size; } @Override public void _parseDetails(ByteBuffer content) { parseVersionAndFlags(content); long entryCount = IsoTypeReader.readUInt32(content); for (int i = 0; i < entryCount; i++) { SubSampleEntry SubSampleEntry = new SubSampleEntry(); SubSampleEntry.setSampleDelta(IsoTypeReader.readUInt32(content)); int subsampleCount = IsoTypeReader.readUInt16(content); for (int j = 0; j < subsampleCount; j++) { SubSampleEntry.SubsampleEntry subsampleEntry = new SubSampleEntry.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)); SubSampleEntry.getSubsampleEntries().add(subsampleEntry); } entries.add(SubSampleEntry); } } @Override protected void getContent(ByteBuffer byteBuffer) { writeVersionAndFlags(byteBuffer); IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); for (SubSampleEntry subSampleEntry : entries) { IsoTypeWriter.writeUInt32(byteBuffer, subSampleEntry.getSampleDelta()); IsoTypeWriter.writeUInt16(byteBuffer, subSampleEntry.getSubsampleCount()); List<SubSampleEntry.SubsampleEntry> subsampleEntries = subSampleEntry.getSubsampleEntries(); for (SubSampleEntry.SubsampleEntry subsampleEntry : subsampleEntries) { if (getVersion() == 1) { IsoTypeWriter.writeUInt32(byteBuffer, subsampleEntry.getSubsampleSize()); } else { IsoTypeWriter.writeUInt16(byteBuffer, CastUtils.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=" + entries.size() + ", entries=" + entries + '}'; } public static class SubSampleEntry { private long sampleDelta; private List<SubsampleEntry> subsampleEntries = new ArrayList<SubsampleEntry>(); public long getSampleDelta() { return sampleDelta; } public void setSampleDelta(long sampleDelta) { this.sampleDelta = sampleDelta; } public int getSubsampleCount() { return subsampleEntries.size(); } public List<SubsampleEntry> getSubsampleEntries() { return subsampleEntries; } @Override public String toString() { return "SampleEntry{" + "sampleDelta=" + sampleDelta + ", subsampleCount=" + subsampleEntries.size() + ", subsampleEntries=" + subsampleEntries + '}'; } 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 + '}'; } } } }