• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 castLabs, Berlin
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.googlecode.mp4parser.boxes.mp4.samplegrouping;
18 
19 import com.coremedia.iso.IsoTypeReader;
20 import com.coremedia.iso.IsoTypeWriter;
21 import com.googlecode.mp4parser.AbstractFullBox;
22 
23 import java.nio.ByteBuffer;
24 import java.util.LinkedList;
25 import java.util.List;
26 
27 import static com.googlecode.mp4parser.util.CastUtils.l2i;
28 
29 /**
30  * This description table gives information about the characteristics of sample groups. The descriptive
31  * information is any other information needed to define or characterize the sample group.
32  * <p/>
33  * There may be multiple instances of this box if there is more than one sample grouping for the samples in a
34  * track. Each instance of the SampleGroupDescription box has a type code that distinguishes different
35  * sample groupings. Within a track, there shall be at most one instance of this box with a particular grouping
36  * type. The associated SampleToGroup shall indicate the same value for the grouping type.
37  * <p/>
38  * The information is stored in the sample group description box after the entry-count. An abstract entry type is
39  * defined and sample groupings shall define derived types to represent the description of each sample group.
40  * For video tracks, an abstract VisualSampleGroupEntry is used with similar types for audio and hint tracks.
41  */
42 public class SampleGroupDescriptionBox extends AbstractFullBox {
43     public static final String TYPE = "sgpd";
44 
45     private String groupingType;
46     private int defaultLength;
47     private List<GroupEntry> groupEntries = new LinkedList<GroupEntry>();
48     private int descriptionLength;
49 
SampleGroupDescriptionBox()50     public SampleGroupDescriptionBox() {
51         super(TYPE);
52     }
53 
54     @Override
getContentSize()55     protected long getContentSize() {
56         long size = 8;
57         if (getVersion() == 1) {
58             size += 4;
59         }
60         size += 4; // entryCount
61         for (GroupEntry groupEntry : groupEntries) {
62             if (getVersion() == 1 && defaultLength == 0) {
63                 size += 4;
64             }
65             size += groupEntry.size();
66         }
67         return size;
68     }
69 
70     @Override
getContent(ByteBuffer byteBuffer)71     protected void getContent(ByteBuffer byteBuffer) {
72         writeVersionAndFlags(byteBuffer);
73         byteBuffer.put(groupingType.getBytes());
74         if (this.getVersion() == 1) {
75             IsoTypeWriter.writeUInt32(byteBuffer, defaultLength);
76         }
77         IsoTypeWriter.writeUInt32(byteBuffer, this.groupEntries.size());
78         for (GroupEntry entry : groupEntries) {
79             if (this.getVersion() == 1 && defaultLength == 0) {
80                 IsoTypeWriter.writeUInt32(byteBuffer, entry.get().limit());
81             }
82             byteBuffer.put(entry.get());
83         }
84     }
85 
86     @Override
_parseDetails(ByteBuffer content)87     protected void _parseDetails(ByteBuffer content) {
88         parseVersionAndFlags(content);
89         if (this.getVersion() != 1) {
90             throw new RuntimeException("SampleGroupDescriptionBox are only supported in version 1");
91         }
92         groupingType = IsoTypeReader.read4cc(content);
93         if (this.getVersion() == 1) {
94             defaultLength = l2i(IsoTypeReader.readUInt32(content));
95         }
96         long entryCount = IsoTypeReader.readUInt32(content);
97         while (entryCount-- > 0) {
98             int length = defaultLength;
99             if (this.getVersion() == 1) {
100                 if (defaultLength == 0) {
101                     descriptionLength = l2i(IsoTypeReader.readUInt32(content));
102                     length = descriptionLength;
103                 }
104             } else {
105                 throw new RuntimeException("This should be implemented");
106             }
107             int finalPos = content.position() + length;
108             ByteBuffer parseMe = content.slice();
109             parseMe.limit(length);
110             groupEntries.add(parseGroupEntry(parseMe, groupingType));
111             content.position(finalPos);
112         }
113 
114     }
115 
parseGroupEntry(ByteBuffer content, String groupingType)116     private GroupEntry parseGroupEntry(ByteBuffer content, String groupingType) {
117         GroupEntry groupEntry;
118         if (RollRecoveryEntry.TYPE.equals(groupingType)) {
119             groupEntry = new RollRecoveryEntry();
120         } else if (RateShareEntry.TYPE.equals(groupingType)) {
121             groupEntry = new RateShareEntry();
122         } else if (CencSampleEncryptionInformationGroupEntry.TYPE.equals(groupingType)) {
123             groupEntry = new CencSampleEncryptionInformationGroupEntry();
124         } else if (VisualRandomAccessEntry.TYPE.equals(groupingType)) {
125             groupEntry = new VisualRandomAccessEntry();
126         } else if (TemporalLevelEntry.TYPE.equals(groupingType)) {
127             groupEntry = new TemporalLevelEntry();
128         } else {
129             groupEntry = new UnknownEntry();
130         }
131         groupEntry.parse(content);
132         return groupEntry;
133     }
134 
135 
getGroupingType()136     public String getGroupingType() {
137         return groupingType;
138     }
139 
setGroupingType(String groupingType)140     public void setGroupingType(String groupingType) {
141         this.groupingType = groupingType;
142     }
143 
getDefaultLength()144     public int getDefaultLength() {
145         return defaultLength;
146     }
147 
setDefaultLength(int defaultLength)148     public void setDefaultLength(int defaultLength) {
149         this.defaultLength = defaultLength;
150     }
151 
getGroupEntries()152     public List<GroupEntry> getGroupEntries() {
153         return groupEntries;
154     }
155 
setGroupEntries(List<GroupEntry> groupEntries)156     public void setGroupEntries(List<GroupEntry> groupEntries) {
157         this.groupEntries = groupEntries;
158     }
159 
160     @Override
equals(Object o)161     public boolean equals(Object o) {
162         if (this == o) {
163             return true;
164         }
165         if (o == null || getClass() != o.getClass()) {
166             return false;
167         }
168 
169         SampleGroupDescriptionBox that = (SampleGroupDescriptionBox) o;
170 
171         if (defaultLength != that.defaultLength) {
172             return false;
173         }
174         if (groupEntries != null ? !groupEntries.equals(that.groupEntries) : that.groupEntries != null) {
175             return false;
176         }
177         if (groupingType != null ? !groupingType.equals(that.groupingType) : that.groupingType != null) {
178             return false;
179         }
180 
181         return true;
182     }
183 
184     @Override
hashCode()185     public int hashCode() {
186         int result = groupingType != null ? groupingType.hashCode() : 0;
187         result = 31 * result + defaultLength;
188         result = 31 * result + (groupEntries != null ? groupEntries.hashCode() : 0);
189         return result;
190     }
191 
192     @Override
toString()193     public String toString() {
194         return "SampleGroupDescriptionBox{" +
195                 "groupingType='" + groupingType + '\'' +
196                 ", defaultLength=" + defaultLength +
197                 ", groupEntries=" + groupEntries +
198                 '}';
199     }
200 }
201