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