1 /*
2  * Copyright 2008 CoreMedia AG, Hamburg
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.coremedia.iso.boxes;
18 
19 
20 import com.coremedia.iso.IsoTypeReader;
21 import com.coremedia.iso.IsoTypeWriter;
22 import com.googlecode.mp4parser.AbstractFullBox;
23 
24 import java.nio.ByteBuffer;
25 
26 /**
27  * This box specifies the characteristics of a single track. Exactly one Track Header Box is contained in a track.<br>
28  * In the absence of an edit list, the presentation of a track starts at the beginning of the overall presentation. An
29  * empty edit is used to offset the start time of a track. <br>
30  * The default value of the track header flags for media tracks is 7 (track_enabled, track_in_movie,
31  * track_in_preview). If in a presentation all tracks have neither track_in_movie nor track_in_preview set, then all
32  * tracks shall be treated as if both flags were set on all tracks. Hint tracks should have the track header flags set
33  * to 0, so that they are ignored for local playback and preview.
34  */
35 public class TrackHeaderBox extends AbstractFullBox {
36 
37     public static final String TYPE = "tkhd";
38 
39     private long creationTime;
40     private long modificationTime;
41     private long trackId;
42     private long duration;
43     private int layer;
44     private int alternateGroup;
45     private float volume;
46     private long[] matrix = new long[]{0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000};
47     private double width;
48     private double height;
49 
50 
TrackHeaderBox()51     public TrackHeaderBox() {
52         super(TYPE);
53 
54     }
55 
getCreationTime()56     public long getCreationTime() {
57         return creationTime;
58     }
59 
getModificationTime()60     public long getModificationTime() {
61         return modificationTime;
62     }
63 
getTrackId()64     public long getTrackId() {
65         return trackId;
66     }
67 
getDuration()68     public long getDuration() {
69         return duration;
70     }
71 
getLayer()72     public int getLayer() {
73         return layer;
74     }
75 
getAlternateGroup()76     public int getAlternateGroup() {
77         return alternateGroup;
78     }
79 
getVolume()80     public float getVolume() {
81         return volume;
82     }
83 
getMatrix()84     public long[] getMatrix() {
85         return matrix;
86     }
87 
getWidth()88     public double getWidth() {
89         return width;
90     }
91 
getHeight()92     public double getHeight() {
93         return height;
94     }
95 
getContentSize()96     protected long getContentSize() {
97         long contentSize = 4;
98         if (getVersion() == 1) {
99             contentSize += 32;
100         } else {
101             contentSize += 20;
102         }
103         contentSize += 60;
104         return contentSize;
105     }
106 
107     @Override
_parseDetails(ByteBuffer content)108     public void _parseDetails(ByteBuffer content) {
109         parseVersionAndFlags(content);
110         if (getVersion() == 1) {
111             creationTime = IsoTypeReader.readUInt64(content);
112             modificationTime = IsoTypeReader.readUInt64(content);
113             trackId = IsoTypeReader.readUInt32(content);
114             IsoTypeReader.readUInt32(content);
115             duration = IsoTypeReader.readUInt64(content);
116         } else {
117             creationTime = IsoTypeReader.readUInt32(content);
118             modificationTime = IsoTypeReader.readUInt32(content);
119             trackId = IsoTypeReader.readUInt32(content);
120             IsoTypeReader.readUInt32(content);
121             duration = IsoTypeReader.readUInt32(content);
122         } // 196
123         IsoTypeReader.readUInt32(content);
124         IsoTypeReader.readUInt32(content);
125         layer = IsoTypeReader.readUInt16(content);    // 204
126         alternateGroup = IsoTypeReader.readUInt16(content);
127         volume = IsoTypeReader.readFixedPoint88(content);
128         IsoTypeReader.readUInt16(content);     // 212
129         matrix = new long[9];
130         for (int i = 0; i < 9; i++) {
131             matrix[i] = IsoTypeReader.readUInt32(content);
132         }
133         width = IsoTypeReader.readFixedPoint1616(content);    // 248
134         height = IsoTypeReader.readFixedPoint1616(content);
135     }
136 
getContent(ByteBuffer byteBuffer)137     public void getContent(ByteBuffer byteBuffer) {
138         writeVersionAndFlags(byteBuffer);
139         if (getVersion() == 1) {
140             IsoTypeWriter.writeUInt64(byteBuffer, creationTime);
141             IsoTypeWriter.writeUInt64(byteBuffer, modificationTime);
142             IsoTypeWriter.writeUInt32(byteBuffer, trackId);
143             IsoTypeWriter.writeUInt32(byteBuffer, 0);
144             IsoTypeWriter.writeUInt64(byteBuffer, duration);
145         } else {
146             IsoTypeWriter.writeUInt32(byteBuffer, creationTime);
147             IsoTypeWriter.writeUInt32(byteBuffer, modificationTime);
148             IsoTypeWriter.writeUInt32(byteBuffer, trackId);
149             IsoTypeWriter.writeUInt32(byteBuffer, 0);
150             IsoTypeWriter.writeUInt32(byteBuffer, duration);
151         } // 196
152         IsoTypeWriter.writeUInt32(byteBuffer, 0);
153         IsoTypeWriter.writeUInt32(byteBuffer, 0);
154         IsoTypeWriter.writeUInt16(byteBuffer, layer);
155         IsoTypeWriter.writeUInt16(byteBuffer, alternateGroup);
156         IsoTypeWriter.writeFixedPont88(byteBuffer, volume);
157         IsoTypeWriter.writeUInt16(byteBuffer, 0);
158         for (int i = 0; i < 9; i++) {
159             IsoTypeWriter.writeUInt32(byteBuffer, matrix[i]);
160         }
161         IsoTypeWriter.writeFixedPont1616(byteBuffer, width);
162         IsoTypeWriter.writeFixedPont1616(byteBuffer, height);
163     }
164 
toString()165     public String toString() {
166         StringBuilder result = new StringBuilder();
167         result.append("TrackHeaderBox[");
168         result.append("creationTime=").append(getCreationTime());
169         result.append(";");
170         result.append("modificationTime=").append(getModificationTime());
171         result.append(";");
172         result.append("trackId=").append(getTrackId());
173         result.append(";");
174         result.append("duration=").append(getDuration());
175         result.append(";");
176         result.append("layer=").append(getLayer());
177         result.append(";");
178         result.append("alternateGroup=").append(getAlternateGroup());
179         result.append(";");
180         result.append("volume=").append(getVolume());
181         for (int i = 0; i < matrix.length; i++) {
182             result.append(";");
183             result.append("matrix").append(i).append("=").append(matrix[i]);
184         }
185         result.append(";");
186         result.append("width=").append(getWidth());
187         result.append(";");
188         result.append("height=").append(getHeight());
189         result.append("]");
190         return result.toString();
191     }
192 
setCreationTime(long creationTime)193     public void setCreationTime(long creationTime) {
194         this.creationTime = creationTime;
195     }
196 
setModificationTime(long modificationTime)197     public void setModificationTime(long modificationTime) {
198         this.modificationTime = modificationTime;
199     }
200 
setTrackId(long trackId)201     public void setTrackId(long trackId) {
202         this.trackId = trackId;
203     }
204 
setDuration(long duration)205     public void setDuration(long duration) {
206         this.duration = duration;
207     }
208 
setLayer(int layer)209     public void setLayer(int layer) {
210         this.layer = layer;
211     }
212 
setAlternateGroup(int alternateGroup)213     public void setAlternateGroup(int alternateGroup) {
214         this.alternateGroup = alternateGroup;
215     }
216 
setVolume(float volume)217     public void setVolume(float volume) {
218         this.volume = volume;
219     }
220 
setMatrix(long[] matrix)221     public void setMatrix(long[] matrix) {
222         this.matrix = matrix;
223     }
224 
setWidth(double width)225     public void setWidth(double width) {
226         this.width = width;
227     }
228 
setHeight(double height)229     public void setHeight(double height) {
230         this.height = height;
231     }
232 
233 
isEnabled()234     public boolean isEnabled() {
235         return (getFlags() & 1) > 0;
236     }
237 
isInMovie()238     public boolean isInMovie() {
239         return (getFlags() & 2) > 0;
240     }
241 
isInPreview()242     public boolean isInPreview() {
243         return (getFlags() & 4) > 0;
244     }
245 
isInPoster()246     public boolean isInPoster() {
247         return (getFlags() & 8) > 0;
248     }
249 }
250