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.sampleentry; 18 19 import com.coremedia.iso.BoxParser; 20 import com.coremedia.iso.IsoTypeReader; 21 import com.coremedia.iso.IsoTypeWriter; 22 import com.coremedia.iso.boxes.Box; 23 import com.coremedia.iso.boxes.ContainerBox; 24 25 import java.nio.ByteBuffer; 26 27 /** 28 * Contains basic information about the audio samples in this track. Format-specific information 29 * is appened as boxes after the data described in ISO/IEC 14496-12 chapter 8.16.2. 30 */ 31 public class AudioSampleEntry extends SampleEntry implements ContainerBox { 32 33 public static final String TYPE1 = "samr"; 34 public static final String TYPE2 = "sawb"; 35 public static final String TYPE3 = "mp4a"; 36 public static final String TYPE4 = "drms"; 37 public static final String TYPE5 = "alac"; 38 public static final String TYPE7 = "owma"; 39 public static final String TYPE8 = "ac-3"; /* ETSI TS 102 366 1.2.1 Annex F */ 40 public static final String TYPE9 = "ec-3"; /* ETSI TS 102 366 1.2.1 Annex F */ 41 public static final String TYPE10 = "mlpa"; 42 public static final String TYPE11 = "dtsl"; 43 public static final String TYPE12 = "dtsh"; 44 public static final String TYPE13 = "dtse"; 45 46 /** 47 * Identifier for an encrypted audio track. 48 * 49 * @see com.coremedia.iso.boxes.ProtectionSchemeInformationBox 50 */ 51 public static final String TYPE_ENCRYPTED = "enca"; 52 53 private int channelCount; 54 private int sampleSize; 55 private long sampleRate; 56 private int soundVersion; 57 private int compressionId; 58 private int packetSize; 59 private long samplesPerPacket; 60 private long bytesPerPacket; 61 private long bytesPerFrame; 62 private long bytesPerSample; 63 64 private int reserved1; 65 private long reserved2; 66 private byte[] soundVersion2Data; 67 private BoxParser boxParser; 68 AudioSampleEntry(String type)69 public AudioSampleEntry(String type) { 70 super(type); 71 } 72 getChannelCount()73 public int getChannelCount() { 74 return channelCount; 75 } 76 getSampleSize()77 public int getSampleSize() { 78 return sampleSize; 79 } 80 getSampleRate()81 public long getSampleRate() { 82 return sampleRate; 83 } 84 getSoundVersion()85 public int getSoundVersion() { 86 return soundVersion; 87 } 88 getCompressionId()89 public int getCompressionId() { 90 return compressionId; 91 } 92 getPacketSize()93 public int getPacketSize() { 94 return packetSize; 95 } 96 getSamplesPerPacket()97 public long getSamplesPerPacket() { 98 return samplesPerPacket; 99 } 100 getBytesPerPacket()101 public long getBytesPerPacket() { 102 return bytesPerPacket; 103 } 104 getBytesPerFrame()105 public long getBytesPerFrame() { 106 return bytesPerFrame; 107 } 108 getBytesPerSample()109 public long getBytesPerSample() { 110 return bytesPerSample; 111 } 112 getSoundVersion2Data()113 public byte[] getSoundVersion2Data() { 114 return soundVersion2Data; 115 } 116 getReserved1()117 public int getReserved1() { 118 return reserved1; 119 } 120 getReserved2()121 public long getReserved2() { 122 return reserved2; 123 } 124 setChannelCount(int channelCount)125 public void setChannelCount(int channelCount) { 126 this.channelCount = channelCount; 127 } 128 setSampleSize(int sampleSize)129 public void setSampleSize(int sampleSize) { 130 this.sampleSize = sampleSize; 131 } 132 setSampleRate(long sampleRate)133 public void setSampleRate(long sampleRate) { 134 this.sampleRate = sampleRate; 135 } 136 setSoundVersion(int soundVersion)137 public void setSoundVersion(int soundVersion) { 138 this.soundVersion = soundVersion; 139 } 140 setCompressionId(int compressionId)141 public void setCompressionId(int compressionId) { 142 this.compressionId = compressionId; 143 } 144 setPacketSize(int packetSize)145 public void setPacketSize(int packetSize) { 146 this.packetSize = packetSize; 147 } 148 setSamplesPerPacket(long samplesPerPacket)149 public void setSamplesPerPacket(long samplesPerPacket) { 150 this.samplesPerPacket = samplesPerPacket; 151 } 152 setBytesPerPacket(long bytesPerPacket)153 public void setBytesPerPacket(long bytesPerPacket) { 154 this.bytesPerPacket = bytesPerPacket; 155 } 156 setBytesPerFrame(long bytesPerFrame)157 public void setBytesPerFrame(long bytesPerFrame) { 158 this.bytesPerFrame = bytesPerFrame; 159 } 160 setBytesPerSample(long bytesPerSample)161 public void setBytesPerSample(long bytesPerSample) { 162 this.bytesPerSample = bytesPerSample; 163 } 164 setReserved1(int reserved1)165 public void setReserved1(int reserved1) { 166 this.reserved1 = reserved1; 167 } 168 setReserved2(long reserved2)169 public void setReserved2(long reserved2) { 170 this.reserved2 = reserved2; 171 } 172 setSoundVersion2Data(byte[] soundVersion2Data)173 public void setSoundVersion2Data(byte[] soundVersion2Data) { 174 this.soundVersion2Data = soundVersion2Data; 175 } 176 setBoxParser(BoxParser boxParser)177 public void setBoxParser(BoxParser boxParser) { 178 this.boxParser = boxParser; 179 } 180 181 @Override _parseDetails(ByteBuffer content)182 public void _parseDetails(ByteBuffer content) { 183 _parseReservedAndDataReferenceIndex(content); //parses the six reserved bytes and dataReferenceIndex 184 // 8 bytes already parsed 185 //reserved bits - used by qt 186 soundVersion = IsoTypeReader.readUInt16(content); 187 188 //reserved 189 reserved1 = IsoTypeReader.readUInt16(content); 190 reserved2 = IsoTypeReader.readUInt32(content); 191 192 channelCount = IsoTypeReader.readUInt16(content); 193 sampleSize = IsoTypeReader.readUInt16(content); 194 //reserved bits - used by qt 195 compressionId = IsoTypeReader.readUInt16(content); 196 //reserved bits - used by qt 197 packetSize = IsoTypeReader.readUInt16(content); 198 //sampleRate = in.readFixedPoint1616(); 199 sampleRate = IsoTypeReader.readUInt32(content); 200 if (!type.equals("mlpa")) { 201 sampleRate = sampleRate >>> 16; 202 } 203 204 //more qt stuff - see http://mp4v2.googlecode.com/svn-history/r388/trunk/src/atom_sound.cpp 205 if (soundVersion > 0) { 206 samplesPerPacket = IsoTypeReader.readUInt32(content); 207 bytesPerPacket = IsoTypeReader.readUInt32(content); 208 bytesPerFrame = IsoTypeReader.readUInt32(content); 209 bytesPerSample = IsoTypeReader.readUInt32(content); 210 } 211 if (soundVersion == 2) { 212 213 soundVersion2Data = new byte[20]; 214 content.get(20); 215 } 216 _parseChildBoxes(content); 217 218 } 219 220 221 @Override getContentSize()222 protected long getContentSize() { 223 long contentSize = 28; 224 contentSize += soundVersion > 0 ? 16 : 0; 225 contentSize += soundVersion == 2 ? 20 : 0; 226 for (Box boxe : boxes) { 227 contentSize += boxe.getSize(); 228 } 229 return contentSize; 230 } 231 232 @Override toString()233 public String toString() { 234 return "AudioSampleEntry{" + 235 "bytesPerSample=" + bytesPerSample + 236 ", bytesPerFrame=" + bytesPerFrame + 237 ", bytesPerPacket=" + bytesPerPacket + 238 ", samplesPerPacket=" + samplesPerPacket + 239 ", packetSize=" + packetSize + 240 ", compressionId=" + compressionId + 241 ", soundVersion=" + soundVersion + 242 ", sampleRate=" + sampleRate + 243 ", sampleSize=" + sampleSize + 244 ", channelCount=" + channelCount + 245 ", boxes=" + getBoxes() + 246 '}'; 247 } 248 249 @Override getContent(ByteBuffer byteBuffer)250 protected void getContent(ByteBuffer byteBuffer) { 251 _writeReservedAndDataReferenceIndex(byteBuffer); 252 IsoTypeWriter.writeUInt16(byteBuffer, soundVersion); 253 IsoTypeWriter.writeUInt16(byteBuffer, reserved1); 254 IsoTypeWriter.writeUInt32(byteBuffer, reserved2); 255 IsoTypeWriter.writeUInt16(byteBuffer, channelCount); 256 IsoTypeWriter.writeUInt16(byteBuffer, sampleSize); 257 IsoTypeWriter.writeUInt16(byteBuffer, compressionId); 258 IsoTypeWriter.writeUInt16(byteBuffer, packetSize); 259 //isos.writeFixedPont1616(getSampleRate()); 260 if (type.equals("mlpa")) { 261 IsoTypeWriter.writeUInt32(byteBuffer, getSampleRate()); 262 } else { 263 IsoTypeWriter.writeUInt32(byteBuffer, getSampleRate() << 16); 264 } 265 266 if (soundVersion > 0) { 267 IsoTypeWriter.writeUInt32(byteBuffer, samplesPerPacket); 268 IsoTypeWriter.writeUInt32(byteBuffer, bytesPerPacket); 269 IsoTypeWriter.writeUInt32(byteBuffer, bytesPerFrame); 270 IsoTypeWriter.writeUInt32(byteBuffer, bytesPerSample); 271 } 272 273 if (soundVersion == 2) { 274 byteBuffer.put(soundVersion2Data); 275 } 276 _writeChildBoxes(byteBuffer); 277 } 278 } 279