/**
* MediaFrame is an Open Source streaming media platform in Java
* which provides a fast, easy to implement and extremely small applet
* that enables to view your audio/video content without having
* to rely on external player applications or bulky plug-ins.
*
* Copyright (C) 2004/5 MediaFrame (http://www.mediaframe.org).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
/**
This software module was originally developed by Apple Computer, Inc.
in the course of development of MPEG-4.
This software module is an implementation of a part of one or
more MPEG-4 tools as specified by MPEG-4.
ISO/IEC gives users of MPEG-4 free license to this
software module or modifications thereof for use in hardware
or software products claiming conformance to MPEG-4.
Those intending to use this software module in hardware or software
products are advised that its use may infringe existing patents.
The original developer of this software module and his/her company,
the subsequent editors and their companies, and ISO/IEC have no
liability for use of this software module or modifications thereof
in an implementation.
Copyright is not released for non MPEG-4 conforming
products. Apple Computer, Inc. retains full right to use the code for its own
purpose, assign or donate the code to a third party and to
inhibit third parties from using the code for non
MPEG-4 conforming products.
This copyright notice must be included in all copies or
derivative works. Copyright (c) 1999, 2000.
*/
package mediaframe.mpeg4.isofile;
import java.io.IOException;
import java.util.Vector;
import org.ripple.power.sound.DataStream;
/**
* MP4Descriptor
*
*/
public class MP4Descriptor {
public final static int MP4ES_DescriptorTag = 3;
public final static int MP4DecoderConfigDescriptorTag = 4;
public final static int MP4DecSpecificInfoDescriptorTag = 5;
protected int type;
protected int size;
protected int readed;
protected Vector children = new Vector();
public MP4Descriptor(int type, int size) {
super();
this.readed = 0;
this.type = type;
this.size = size;
}
public static MP4Descriptor createDescriptor(DataStream bitstream)
throws IOException {
int tag = (int) bitstream.readBytes(1);
int readed = 1;
int size = 0;
int b = 0;
do {
b = (int) bitstream.readBytes(1);
size <<= 7;
size |= b & 0x7f;
readed++;
} while ((b & 0x80) == 0x80);
MP4Descriptor descriptor = new MP4Descriptor(tag, size);
switch (tag) {
case MP4ES_DescriptorTag:
descriptor.createES_Descriptor(bitstream);
break;
case MP4DecoderConfigDescriptorTag:
descriptor.createDecoderConfigDescriptor(bitstream);
break;
case MP4DecSpecificInfoDescriptorTag:
descriptor.createDecSpecificInfoDescriptor(bitstream);
break;
default:
break;
}
bitstream.skipBytes(descriptor.size - descriptor.readed);
descriptor.readed = readed + descriptor.size;
return descriptor;
}
/**
* Loads the MP4ES_Descriptor from the input bitstream.
*
* @param bitstream
* the input bitstream
*/
public void createES_Descriptor(DataStream bitstream) throws IOException {
bitstream.readBytes(2);
int flags = (int) bitstream.readBytes(1);
boolean streamDependenceFlag = (flags & (1 << 7)) != 0;
boolean urlFlag = (flags & (1 << 6)) != 0;
boolean ocrFlag = (flags & (1 << 5)) != 0;
readed += 3;
if (streamDependenceFlag) {
bitstream.skipBytes(2);
readed += 2;
}
if (urlFlag) {
int str_size = (int) bitstream.readBytes(1);
bitstream.readString(str_size);
readed += str_size + 1;
}
if (ocrFlag) {
bitstream.skipBytes(2);
readed += 2;
}
while (readed < size) {
MP4Descriptor descriptor = createDescriptor(bitstream);
children.addElement(descriptor);
readed += descriptor.getReaded();
}
}
/**
* Loads the MP4DecoderConfigDescriptor from the input bitstream.
*
* @param bitstream
* the input bitstream
*/
public void createDecoderConfigDescriptor(DataStream bitstream)
throws IOException {
bitstream.readBytes(1);
int value = (int) bitstream.readBytes(1);
value = (int) bitstream.readBytes(2);
int bufferSizeDB = value << 8;
value = (int) bitstream.readBytes(1);
bufferSizeDB |= value & 0xff;
bitstream.readBytes(4);
bitstream.readBytes(4);
readed += 13;
if (readed < size) {
MP4Descriptor descriptor = createDescriptor(bitstream);
children.addElement(descriptor);
readed += descriptor.getReaded();
}
}
protected int decSpecificDataSize;
protected long decSpecificDataOffset;
/**
* Loads the MP4DecSpecificInfoDescriptor from the input bitstream.
*
* @param bitstream
* the input bitstream
*/
public void createDecSpecificInfoDescriptor(DataStream bitstream)
throws IOException {
decSpecificDataOffset = bitstream.getOffset();
decSpecificDataSize = size - readed;
}
public long getDecSpecificDataOffset() {
return decSpecificDataOffset;
}
public int getDecSpecificDataSize() {
return decSpecificDataSize;
}
/**
* Lookups for a child descriptor with the specified <code>type</code>,
* skips the <code>number</code> children with the same type before finding
* a result.
*
* @param type
* the type of the descriptor.
* @param number
* the number of child descriptors to skip
* @return the descriptor which was being searched.
*/
public MP4Descriptor lookup(int type, int number) {
int position = 0;
for (int i = 0; i < children.size(); i++) {
MP4Descriptor descriptor = (MP4Descriptor) children.elementAt(i);
if (descriptor.getType() == type) {
if (position >= number) {
return descriptor;
}
position++;
}
}
return null;
}
/**
* Returns the type of this descriptor.
*/
public int getType() {
return type;
}
/**
* Gets the number of data bytes which were readed from the stream;
*
* @return the number of readed data bytes.
*/
public int getReaded() {
return readed;
}
}