/*
* Copyright (C) 2011 in-somnia
*
* This file is part of JAAD.
*
* JAAD is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* JAAD 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 Lesser General
* Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* If not, see <http://www.gnu.org/licenses/>.
*/
package net.sourceforge.jaad.mp4.od;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.jaad.mp4.MP4InputStream;
/**
* The abstract base class and factory for all descriptors (defined in ISO
* 14496-1 as 'ObjectDescriptors').
*
* @author in-somnia
*/
public abstract class Descriptor {
public static final int TYPE_OBJECT_DESCRIPTOR = 1;
public static final int TYPE_INITIAL_OBJECT_DESCRIPTOR = 2;
public static final int TYPE_ES_DESCRIPTOR = 3;
public static final int TYPE_DECODER_CONFIG_DESCRIPTOR = 4;
public static final int TYPE_DECODER_SPECIFIC_INFO = 5;
public static final int TYPE_SL_CONFIG_DESCRIPTOR = 6;
public static final int TYPE_ES_ID_INC = 14;
public static final int TYPE_MP4_INITIAL_OBJECT_DESCRIPTOR = 16;
public static Descriptor createDescriptor(MP4InputStream in) throws IOException {
//read tag and size
final int type = in.read();
int read = 1;
int size = 0;
int b = 0;
do {
b = in.read();
size <<= 7;
size |= b&0x7f;
read++;
}
while((b&0x80)==0x80);
//create descriptor
final Descriptor desc = forTag(type);
desc.type = type;
desc.size = size;
desc.start = in.getOffset();
//decode
desc.decode(in);
//skip remaining bytes
final long remaining = size-(in.getOffset()-desc.start);
if(remaining>0) {
Logger.getLogger("MP4 Boxes").log(Level.INFO, "Descriptor: bytes left: {0}, offset: {1}", new Long[]{remaining, in.getOffset()});
in.skipBytes(remaining);
}
desc.size += read; //include type and size fields
return desc;
}
private static Descriptor forTag(int tag) {
Descriptor desc;
switch(tag) {
case TYPE_OBJECT_DESCRIPTOR:
desc = new ObjectDescriptor();
break;
case TYPE_INITIAL_OBJECT_DESCRIPTOR:
case TYPE_MP4_INITIAL_OBJECT_DESCRIPTOR:
desc = new InitialObjectDescriptor();
break;
case TYPE_ES_DESCRIPTOR:
desc = new ESDescriptor();
break;
case TYPE_DECODER_CONFIG_DESCRIPTOR:
desc = new DecoderConfigDescriptor();
break;
case TYPE_DECODER_SPECIFIC_INFO:
desc = new DecoderSpecificInfo();
break;
case TYPE_SL_CONFIG_DESCRIPTOR:
//desc = new SLConfigDescriptor();
//break;
default:
Logger.getLogger("MP4 Boxes").log(Level.INFO, "Unknown descriptor type: {0}", tag);
desc = new UnknownDescriptor();
}
return desc;
}
protected int type, size;
protected long start;
private List<Descriptor> children;
protected Descriptor() {
children = new ArrayList<Descriptor>();
}
abstract void decode(MP4InputStream in) throws IOException;
//children
protected void readChildren(MP4InputStream in) throws IOException {
Descriptor desc;
while((size-(in.getOffset()-start))>0) {
desc = createDescriptor(in);
children.add(desc);
}
}
public List<Descriptor> getChildren() {
return Collections.unmodifiableList(children);
}
//getter
public int getType() {
return type;
}
public int getSize() {
return size;
}
}