Home | History | Annotate | Download | only in sampleentry
      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.googlecode.mp4parser.AbstractBox;
     23 import com.coremedia.iso.boxes.Box;
     24 import com.coremedia.iso.boxes.ContainerBox;
     25 import com.googlecode.mp4parser.util.ByteBufferByteChannel;
     26 
     27 import java.io.ByteArrayOutputStream;
     28 import java.io.IOException;
     29 import java.nio.ByteBuffer;
     30 import java.nio.channels.Channels;
     31 import java.nio.channels.ReadableByteChannel;
     32 import java.nio.channels.WritableByteChannel;
     33 import java.util.ArrayList;
     34 import java.util.LinkedList;
     35 import java.util.List;
     36 
     37 /**
     38  * Abstract base class for all sample entries.
     39  *
     40  * @see com.coremedia.iso.boxes.sampleentry.AudioSampleEntry
     41  * @see com.coremedia.iso.boxes.sampleentry.VisualSampleEntry
     42  * @see com.coremedia.iso.boxes.sampleentry.TextSampleEntry
     43  */
     44 public abstract class SampleEntry extends AbstractBox implements ContainerBox {
     45 
     46 
     47     private int dataReferenceIndex = 1;
     48     protected List<Box> boxes = new LinkedList<Box>();
     49     private BoxParser boxParser;
     50 
     51 
     52     protected SampleEntry(String type) {
     53         super(type);
     54     }
     55 
     56     public void setType(String type) {
     57         this.type = type;
     58     }
     59 
     60     public int getDataReferenceIndex() {
     61         return dataReferenceIndex;
     62     }
     63 
     64     public void setDataReferenceIndex(int dataReferenceIndex) {
     65         this.dataReferenceIndex = dataReferenceIndex;
     66     }
     67 
     68     public void setBoxes(List<Box> boxes) {
     69         this.boxes = new LinkedList<Box>(boxes);
     70     }
     71 
     72     public void addBox(Box b) {
     73         b.setParent(this);
     74         boxes.add(b);
     75     }
     76 
     77     public boolean removeBox(Box b) {
     78         b.setParent(this);
     79         return boxes.remove(b);
     80     }
     81 
     82     public List<Box> getBoxes() {
     83         return boxes;
     84     }
     85 
     86     @SuppressWarnings("unchecked")
     87     public <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive) {
     88         List<T> boxesToBeReturned = new ArrayList<T>(2);
     89         for (Box boxe : boxes) { //clazz.isInstance(boxe) / clazz == boxe.getClass()?
     90             if (clazz == boxe.getClass()) {
     91                 boxesToBeReturned.add((T) boxe);
     92             }
     93 
     94             if (recursive && boxe instanceof ContainerBox) {
     95                 boxesToBeReturned.addAll(((ContainerBox) boxe).getBoxes(clazz, recursive));
     96             }
     97         }
     98         // Optimize here! Spare object creation work on arrays directly! System.arrayCopy
     99         return boxesToBeReturned;
    100         //return (T[]) boxesToBeReturned.toArray();
    101     }
    102 
    103     @SuppressWarnings("unchecked")
    104     public <T extends Box> List<T> getBoxes(Class<T> clazz) {
    105         return getBoxes(clazz, false);
    106     }
    107 
    108     @Override
    109     public void parse(ReadableByteChannel readableByteChannel, ByteBuffer header, long contentSize, BoxParser boxParser) throws IOException {
    110         this.boxParser = boxParser;
    111         super.parse(readableByteChannel, header, contentSize, boxParser);
    112 
    113     }
    114 
    115 
    116     public void _parseReservedAndDataReferenceIndex(ByteBuffer content) {
    117         content.get(new byte[6]); // ignore 6 reserved bytes;
    118         dataReferenceIndex = IsoTypeReader.readUInt16(content);
    119     }
    120 
    121     public void _parseChildBoxes(ByteBuffer content) {
    122         while (content.remaining() > 8) {
    123             try {
    124                 boxes.add(boxParser.parseBox(new ByteBufferByteChannel(content), this));
    125             } catch (IOException e) {
    126                 throw new RuntimeException(e);
    127             }
    128 
    129         }
    130         setDeadBytes(content.slice());
    131     }
    132 
    133     public void _writeReservedAndDataReferenceIndex(ByteBuffer bb) {
    134         bb.put(new byte[6]);
    135         IsoTypeWriter.writeUInt16(bb, dataReferenceIndex);
    136     }
    137 
    138     public void _writeChildBoxes(ByteBuffer bb) {
    139         ByteArrayOutputStream baos = new ByteArrayOutputStream();
    140         WritableByteChannel wbc = Channels.newChannel(baos);
    141         try {
    142             for (Box box : boxes) {
    143                 box.getBox(wbc);
    144             }
    145             wbc.close();
    146         } catch (IOException e) {
    147             throw new RuntimeException("Cannot happen. Everything should be in memory and therefore no exceptions.");
    148         }
    149         bb.put(baos.toByteArray());
    150     }
    151 
    152     public long getNumOfBytesToFirstChild() {
    153         long sizeOfChildren = 0;
    154         for (Box box : boxes) {
    155             sizeOfChildren += box.getSize();
    156         }
    157         return getSize() - sizeOfChildren;
    158     }
    159 
    160 }
    161