/* | |
* Copyright 2011 castLabs, Berlin | |
* | |
* Licensed under the Apache License, Version 2.0 (the License); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an AS IS BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package com.googlecode.mp4parser.boxes.mp4.objectdescriptors; | |
import com.coremedia.iso.Hex; | |
import com.coremedia.iso.IsoTypeReader; | |
import com.coremedia.iso.IsoTypeWriter; | |
import java.io.IOException; | |
import java.nio.ByteBuffer; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.List; | |
import java.util.logging.Logger; | |
/** | |
* class DecoderConfigDescriptor extends BaseDescriptor : bit(8) | |
* tag=DecoderConfigDescrTag { | |
* bit(8) objectTypeIndication; | |
* bit(6) streamType; | |
* bit(1) upStream; | |
* const bit(1) reserved=1; | |
* bit(24) bufferSizeDB; | |
* bit(32) maxBitrate; | |
* bit(32) avgBitrate; | |
* DecoderSpecificInfo decSpecificInfo[0 .. 1]; | |
* profileLevelIndicationIndexDescriptor profileLevelIndicationIndexDescr | |
* [0..255]; | |
* } | |
*/ | |
@Descriptor(tags = {0x04}) | |
public class DecoderConfigDescriptor extends BaseDescriptor { | |
private static Logger log = Logger.getLogger(DecoderConfigDescriptor.class.getName()); | |
int objectTypeIndication; | |
int streamType; | |
int upStream; | |
int bufferSizeDB; | |
long maxBitRate; | |
long avgBitRate; | |
DecoderSpecificInfo decoderSpecificInfo; | |
AudioSpecificConfig audioSpecificInfo; | |
List<ProfileLevelIndicationDescriptor> profileLevelIndicationDescriptors = new ArrayList<ProfileLevelIndicationDescriptor>(); | |
byte[] configDescriptorDeadBytes; | |
@Override | |
public void parseDetail(ByteBuffer bb) throws IOException { | |
objectTypeIndication = IsoTypeReader.readUInt8(bb); | |
int data = IsoTypeReader.readUInt8(bb); | |
streamType = data >>> 2; | |
upStream = (data >> 1) & 0x1; | |
bufferSizeDB = IsoTypeReader.readUInt24(bb); | |
maxBitRate = IsoTypeReader.readUInt32(bb); | |
avgBitRate = IsoTypeReader.readUInt32(bb); | |
BaseDescriptor descriptor; | |
if (bb.remaining() > 2) { //1byte tag + at least 1byte size | |
final int begin = bb.position(); | |
descriptor = ObjectDescriptorFactory.createFrom(objectTypeIndication, bb); | |
final int read = bb.position() - begin; | |
log.finer(descriptor + " - DecoderConfigDescr1 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null)); | |
if (descriptor != null) { | |
final int size = descriptor.getSize(); | |
if (read < size) { | |
//skip | |
configDescriptorDeadBytes = new byte[size - read]; | |
bb.get(configDescriptorDeadBytes); | |
} | |
} | |
if (descriptor instanceof DecoderSpecificInfo) { | |
decoderSpecificInfo = (DecoderSpecificInfo) descriptor; | |
} | |
if (descriptor instanceof AudioSpecificConfig) { | |
audioSpecificInfo = (AudioSpecificConfig) descriptor; | |
} | |
} | |
while (bb.remaining() > 2) { | |
final long begin = bb.position(); | |
descriptor = ObjectDescriptorFactory.createFrom(objectTypeIndication, bb); | |
final long read = bb.position() - begin; | |
log.finer(descriptor + " - DecoderConfigDescr2 read: " + read + ", size: " + (descriptor != null ? descriptor.getSize() : null)); | |
if (descriptor instanceof ProfileLevelIndicationDescriptor) { | |
profileLevelIndicationDescriptors.add((ProfileLevelIndicationDescriptor) descriptor); | |
} | |
} | |
} | |
public int serializedSize() { | |
return 15 + audioSpecificInfo.serializedSize(); | |
} | |
public ByteBuffer serialize() { | |
ByteBuffer out = ByteBuffer.allocate(serializedSize()); | |
IsoTypeWriter.writeUInt8(out, 4); | |
IsoTypeWriter.writeUInt8(out, serializedSize() - 2); | |
IsoTypeWriter.writeUInt8(out, objectTypeIndication); | |
int flags = (streamType << 2) | (upStream << 1) | 1; | |
IsoTypeWriter.writeUInt8(out, flags); | |
IsoTypeWriter.writeUInt24(out, bufferSizeDB); | |
IsoTypeWriter.writeUInt32(out, maxBitRate); | |
IsoTypeWriter.writeUInt32(out, avgBitRate); | |
out.put(audioSpecificInfo.serialize().array()); | |
return out; | |
} | |
public DecoderSpecificInfo getDecoderSpecificInfo() { | |
return decoderSpecificInfo; | |
} | |
public AudioSpecificConfig getAudioSpecificInfo() { | |
return audioSpecificInfo; | |
} | |
public void setAudioSpecificInfo(AudioSpecificConfig audioSpecificInfo) { | |
this.audioSpecificInfo = audioSpecificInfo; | |
} | |
public List<ProfileLevelIndicationDescriptor> getProfileLevelIndicationDescriptors() { | |
return profileLevelIndicationDescriptors; | |
} | |
public int getObjectTypeIndication() { | |
return objectTypeIndication; | |
} | |
public void setObjectTypeIndication(int objectTypeIndication) { | |
this.objectTypeIndication = objectTypeIndication; | |
} | |
public int getStreamType() { | |
return streamType; | |
} | |
public void setStreamType(int streamType) { | |
this.streamType = streamType; | |
} | |
public int getUpStream() { | |
return upStream; | |
} | |
public void setUpStream(int upStream) { | |
this.upStream = upStream; | |
} | |
public int getBufferSizeDB() { | |
return bufferSizeDB; | |
} | |
public void setBufferSizeDB(int bufferSizeDB) { | |
this.bufferSizeDB = bufferSizeDB; | |
} | |
public long getMaxBitRate() { | |
return maxBitRate; | |
} | |
public void setMaxBitRate(long maxBitRate) { | |
this.maxBitRate = maxBitRate; | |
} | |
public long getAvgBitRate() { | |
return avgBitRate; | |
} | |
public void setAvgBitRate(long avgBitRate) { | |
this.avgBitRate = avgBitRate; | |
} | |
@Override | |
public String toString() { | |
final StringBuilder sb = new StringBuilder(); | |
sb.append("DecoderConfigDescriptor"); | |
sb.append("{objectTypeIndication=").append(objectTypeIndication); | |
sb.append(", streamType=").append(streamType); | |
sb.append(", upStream=").append(upStream); | |
sb.append(", bufferSizeDB=").append(bufferSizeDB); | |
sb.append(", maxBitRate=").append(maxBitRate); | |
sb.append(", avgBitRate=").append(avgBitRate); | |
sb.append(", decoderSpecificInfo=").append(decoderSpecificInfo); | |
sb.append(", audioSpecificInfo=").append(audioSpecificInfo); | |
sb.append(", configDescriptorDeadBytes=").append(Hex.encodeHex(configDescriptorDeadBytes != null ? configDescriptorDeadBytes : new byte[]{})); | |
sb.append(", profileLevelIndicationDescriptors=").append(profileLevelIndicationDescriptors == null ? "null" : Arrays.asList(profileLevelIndicationDescriptors).toString()); | |
sb.append('}'); | |
return sb.toString(); | |
} | |
/*objectTypeIndication values | |
0x00 Forbidden | |
0x01 Systems ISO/IEC 14496-1 a | |
0x02 Systems ISO/IEC 14496-1 b | |
0x03 Interaction Stream | |
0x04 Systems ISO/IEC 14496-1 Extended BIFS Configuration c | |
0x05 Systems ISO/IEC 14496-1 AFX d | |
0x06 Font Data Stream | |
0x07 Synthesized Texture Stream | |
0x08 Streaming Text Stream | |
0x09-0x1F reserved for ISO use | |
0x20 Visual ISO/IEC 14496-2 e | |
0x21 Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10 f | |
0x22 Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10 f | |
0x23-0x3F reserved for ISO use | |
0x40 Audio ISO/IEC 14496-3 g | |
0x41-0x5F reserved for ISO use | |
0x60 Visual ISO/IEC 13818-2 Simple Profile | |
0x61 Visual ISO/IEC 13818-2 Main Profile | |
0x62 Visual ISO/IEC 13818-2 SNR Profile | |
0x63 Visual ISO/IEC 13818-2 Spatial Profile | |
0x64 Visual ISO/IEC 13818-2 High Profile | |
0x65 Visual ISO/IEC 13818-2 422 Profile | |
0x66 Audio ISO/IEC 13818-7 Main Profile | |
0x67 Audio ISO/IEC 13818-7 LowComplexity Profile | |
0x68 Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile | |
0x69 Audio ISO/IEC 13818-3 | |
0x6A Visual ISO/IEC 11172-2 | |
0x6B Audio ISO/IEC 11172-3 | |
0x6C Visual ISO/IEC 10918-1 | |
0x6D reserved for registration authority i | |
0x6E Visual ISO/IEC 15444-1 | |
0x6F - 0x9F reserved for ISO use | |
0xA0 - 0xBF reserved for registration authority i | |
0xC0 - 0xE0 user private | |
0xE1 reserved for registration authority i | |
0xE2 - 0xFE user private | |
0xFF no object type specified h | |
*/ | |
/* streamType values | |
0x00 Forbidden | |
0x01 ObjectDescriptorStream (see 7.2.5) | |
0x02 ClockReferenceStream (see 7.3.2.5) | |
0x03 SceneDescriptionStream (see ISO/IEC 14496-11) | |
0x04 VisualStream | |
0x05 AudioStream | |
0x06 MPEG7Stream | |
0x07 IPMPStream (see 7.2.3.2) | |
0x08 ObjectContentInfoStream (see 7.2.4.2) | |
0x09 MPEGJStream | |
0x0A Interaction Stream | |
0x0B IPMPToolStream (see [ISO/IEC 14496-13]) | |
0x0C - 0x1F reserved for ISO use | |
0x20 - 0x3F user private | |
*/ | |
} |