TrackFragmentHeaderBox.java revision dd9eb897ee7c7b507cbdcf80263bb4b5de6966bf
1/* 2 * Copyright 2009 castLabs GmbH, 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 17package com.coremedia.iso.boxes.fragment; 18 19import com.coremedia.iso.IsoTypeReader; 20import com.coremedia.iso.IsoTypeWriter; 21import com.googlecode.mp4parser.AbstractFullBox; 22 23import java.nio.ByteBuffer; 24 25/** 26 * aligned(8) class TrackFragmentHeaderBox 27 * extends FullBox('tfhd', 0, tf_flags){ 28 * unsigned int(32) track_ID; 29 * // all the following are optional fields 30 * unsigned int(64) base_data_offset; 31 * unsigned int(32) sample_description_index; 32 * unsigned int(32) default_sample_duration; 33 * unsigned int(32) default_sample_size; 34 * unsigned int(32) default_sample_flags 35 * } 36 */ 37public class TrackFragmentHeaderBox extends AbstractFullBox { 38 public static final String TYPE = "tfhd"; 39 40 private long trackId; 41 private long baseDataOffset = -1; 42 private long sampleDescriptionIndex; 43 private long defaultSampleDuration = -1; 44 private long defaultSampleSize = -1; 45 private SampleFlags defaultSampleFlags; 46 private boolean durationIsEmpty; 47 48 public TrackFragmentHeaderBox() { 49 super(TYPE); 50 } 51 52 protected long getContentSize() { 53 long size = 8; 54 int flags = getFlags(); 55 if ((flags & 0x1) == 1) { //baseDataOffsetPresent 56 size += 8; 57 } 58 if ((flags & 0x2) == 0x2) { //sampleDescriptionIndexPresent 59 size += 4; 60 } 61 if ((flags & 0x8) == 0x8) { //defaultSampleDurationPresent 62 size += 4; 63 } 64 if ((flags & 0x10) == 0x10) { //defaultSampleSizePresent 65 size += 4; 66 } 67 if ((flags & 0x20) == 0x20) { //defaultSampleFlagsPresent 68 size += 4; 69 } 70 return size; 71 } 72 73 74 protected void getContent(ByteBuffer byteBuffer) { 75 writeVersionAndFlags(byteBuffer); 76 IsoTypeWriter.writeUInt32(byteBuffer, trackId); 77 78 if ((getFlags() & 0x1) == 1) { //baseDataOffsetPresent 79 IsoTypeWriter.writeUInt64(byteBuffer, getBaseDataOffset()); 80 } 81 if ((getFlags() & 0x2) == 0x2) { //sampleDescriptionIndexPresent 82 IsoTypeWriter.writeUInt32(byteBuffer, getSampleDescriptionIndex()); 83 } 84 if ((getFlags() & 0x8) == 0x8) { //defaultSampleDurationPresent 85 IsoTypeWriter.writeUInt32(byteBuffer, getDefaultSampleDuration()); 86 } 87 if ((getFlags() & 0x10) == 0x10) { //defaultSampleSizePresent 88 IsoTypeWriter.writeUInt32(byteBuffer, getDefaultSampleSize()); 89 } 90 if ((getFlags() & 0x20) == 0x20) { //defaultSampleFlagsPresent 91 defaultSampleFlags.getContent(byteBuffer); 92 } 93 } 94 95 @Override 96 public void _parseDetails(ByteBuffer content) { 97 parseVersionAndFlags(content); 98 trackId = IsoTypeReader.readUInt32(content); 99 if ((getFlags() & 0x1) == 1) { //baseDataOffsetPresent 100 baseDataOffset = IsoTypeReader.readUInt64(content); 101 } 102 if ((getFlags() & 0x2) == 0x2) { //sampleDescriptionIndexPresent 103 sampleDescriptionIndex = IsoTypeReader.readUInt32(content); 104 } 105 if ((getFlags() & 0x8) == 0x8) { //defaultSampleDurationPresent 106 defaultSampleDuration = IsoTypeReader.readUInt32(content); 107 } 108 if ((getFlags() & 0x10) == 0x10) { //defaultSampleSizePresent 109 defaultSampleSize = IsoTypeReader.readUInt32(content); 110 } 111 if ((getFlags() & 0x20) == 0x20) { //defaultSampleFlagsPresent 112 defaultSampleFlags = new SampleFlags(content); 113 } 114 if ((getFlags() & 0x10000) == 0x10000) { //durationIsEmpty 115 durationIsEmpty = true; 116 } 117 } 118 119 public boolean hasBaseDataOffset() { 120 return (getFlags() & 0x1) != 0; 121 } 122 123 public boolean hasSampleDescriptionIndex() { 124 return (getFlags() & 0x2) != 0; 125 } 126 127 public boolean hasDefaultSampleDuration() { 128 return (getFlags() & 0x8) != 0; 129 } 130 131 public boolean hasDefaultSampleSize() { 132 return (getFlags() & 0x10) != 0; 133 } 134 135 public boolean hasDefaultSampleFlags() { 136 return (getFlags() & 0x20) != 0; 137 } 138 139 public long getTrackId() { 140 return trackId; 141 } 142 143 public long getBaseDataOffset() { 144 return baseDataOffset; 145 } 146 147 public long getSampleDescriptionIndex() { 148 return sampleDescriptionIndex; 149 } 150 151 public long getDefaultSampleDuration() { 152 return defaultSampleDuration; 153 } 154 155 public long getDefaultSampleSize() { 156 return defaultSampleSize; 157 } 158 159 public SampleFlags getDefaultSampleFlags() { 160 return defaultSampleFlags; 161 } 162 163 public boolean isDurationIsEmpty() { 164 return durationIsEmpty; 165 } 166 167 public void setTrackId(long trackId) { 168 this.trackId = trackId; 169 } 170 171 public void setBaseDataOffset(long baseDataOffset) { 172 if (baseDataOffset == -1) { 173 setFlags(getFlags() & (Integer.MAX_VALUE ^ 0x1)); 174 } else { 175 setFlags(getFlags() | 0x1); // activate the field 176 } 177 this.baseDataOffset = baseDataOffset; 178 } 179 180 public void setSampleDescriptionIndex(long sampleDescriptionIndex) { 181 if (sampleDescriptionIndex == -1) { 182 setFlags(getFlags() & (Integer.MAX_VALUE ^ 0x2)); 183 } else { 184 setFlags(getFlags() | 0x2); // activate the field 185 } 186 this.sampleDescriptionIndex = sampleDescriptionIndex; 187 } 188 189 public void setDefaultSampleDuration(long defaultSampleDuration) { 190 setFlags(getFlags() | 0x8); // activate the field 191 this.defaultSampleDuration = defaultSampleDuration; 192 } 193 194 public void setDefaultSampleSize(long defaultSampleSize) { 195 setFlags(getFlags() | 0x10); // activate the field 196 this.defaultSampleSize = defaultSampleSize; 197 } 198 199 public void setDefaultSampleFlags(SampleFlags defaultSampleFlags) { 200 setFlags(getFlags() | 0x20); // activate the field 201 this.defaultSampleFlags = defaultSampleFlags; 202 } 203 204 public void setDurationIsEmpty(boolean durationIsEmpty) { 205 setFlags(getFlags() | 0x10000); // activate the field 206 this.durationIsEmpty = durationIsEmpty; 207 } 208 209 @Override 210 public String toString() { 211 final StringBuilder sb = new StringBuilder(); 212 sb.append("TrackFragmentHeaderBox"); 213 sb.append("{trackId=").append(trackId); 214 sb.append(", baseDataOffset=").append(baseDataOffset); 215 sb.append(", sampleDescriptionIndex=").append(sampleDescriptionIndex); 216 sb.append(", defaultSampleDuration=").append(defaultSampleDuration); 217 sb.append(", defaultSampleSize=").append(defaultSampleSize); 218 sb.append(", defaultSampleFlags=").append(defaultSampleFlags); 219 sb.append(", durationIsEmpty=").append(durationIsEmpty); 220 sb.append('}'); 221 return sb.toString(); 222 } 223 224} 225