/* * Copyright 2012 castLabs, Berlin * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mp4parser.boxes.samplegrouping; 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.LinkedList; import java.util.List; /** * <h1>4cc = "{@value #TYPE}"</h1> * <p>This table can be used to find the group that a sample belongs to and the associated description of that * sample group. The table is compactly coded with each entry giving the index of the first sample of a run of * samples with the same sample group descriptor. The sample group description ID is an index that refers to a * SampleGroupDescription box, which contains entries describing the characteristics of each sample group.</p> * <p>There may be multiple instances of this box if there is more than one sample grouping for the samples in a * track. Each instance of the SampleToGroup box has a type code that distinguishes different sample * groupings. Within a track, there shall be at most one instance of this box with a particular grouping type. The * associated SampleGroupDescription shall indicate the same value for the grouping type.</p> * <p>Version 1 of this box should only be used if a grouping type parameter is needed.</p> */ public class SampleToGroupBox extends AbstractFullBox { public static final String TYPE = "sbgp"; List<Entry> entries = new LinkedList<Entry>(); private String groupingType; private String groupingTypeParameter; public SampleToGroupBox() { super(TYPE); } @Override protected long getContentSize() { return this.getVersion() == 1 ? entries.size() * 8 + 16 : entries.size() * 8 + 12; } @Override protected void getContent(ByteBuffer byteBuffer) { writeVersionAndFlags(byteBuffer); byteBuffer.put(groupingType.getBytes()); if (this.getVersion() == 1) { byteBuffer.put(groupingTypeParameter.getBytes()); } IsoTypeWriter.writeUInt32(byteBuffer, entries.size()); for (Entry entry : entries) { IsoTypeWriter.writeUInt32(byteBuffer, entry.getSampleCount()); IsoTypeWriter.writeUInt32(byteBuffer, entry.getGroupDescriptionIndex()); } } @Override protected void _parseDetails(ByteBuffer content) { parseVersionAndFlags(content); groupingType = IsoTypeReader.read4cc(content); if (this.getVersion() == 1) { groupingTypeParameter = IsoTypeReader.read4cc(content); } long entryCount = IsoTypeReader.readUInt32(content); while (entryCount-- > 0) { entries.add(new Entry(CastUtils.l2i(IsoTypeReader.readUInt32(content)), CastUtils.l2i(IsoTypeReader.readUInt32(content)))); } } public String getGroupingType() { return groupingType; } public void setGroupingType(String groupingType) { this.groupingType = groupingType; } public String getGroupingTypeParameter() { return groupingTypeParameter; } public void setGroupingTypeParameter(String groupingTypeParameter) { this.groupingTypeParameter = groupingTypeParameter; } public List<Entry> getEntries() { return entries; } public void setEntries(List<Entry> entries) { this.entries = entries; } public static class Entry { private long sampleCount; private int groupDescriptionIndex; public Entry(long sampleCount, int groupDescriptionIndex) { this.sampleCount = sampleCount; this.groupDescriptionIndex = groupDescriptionIndex; } public long getSampleCount() { return sampleCount; } public void setSampleCount(long sampleCount) { this.sampleCount = sampleCount; } public int getGroupDescriptionIndex() { return groupDescriptionIndex; } public void setGroupDescriptionIndex(int groupDescriptionIndex) { this.groupDescriptionIndex = groupDescriptionIndex; } @Override public String toString() { return "Entry{" + "sampleCount=" + sampleCount + ", groupDescriptionIndex=" + groupDescriptionIndex + '}'; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Entry entry = (Entry) o; if (groupDescriptionIndex != entry.groupDescriptionIndex) { return false; } if (sampleCount != entry.sampleCount) { return false; } return true; } @Override public int hashCode() { int result = (int) (sampleCount ^ (sampleCount >>> 32)); result = 31 * result + groupDescriptionIndex; return result; } } }