Home | History | Annotate | Download | only in boxes
      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;
     18 
     19 
     20 import com.coremedia.iso.IsoTypeReader;
     21 import com.coremedia.iso.IsoTypeReaderVariable;
     22 import com.coremedia.iso.IsoTypeWriter;
     23 import com.coremedia.iso.IsoTypeWriterVariable;
     24 import com.googlecode.mp4parser.AbstractFullBox;
     25 
     26 import java.io.IOException;
     27 import java.nio.ByteBuffer;
     28 import java.util.LinkedList;
     29 import java.util.List;
     30 
     31 /**
     32  * aligned(8) class ItemLocationBox extends FullBox(iloc, version, 0) {
     33  * unsigned int(4) offset_size;
     34  * unsigned int(4) length_size;
     35  * unsigned int(4) base_offset_size;
     36  * if (version == 1)
     37  * unsigned int(4) index_size;
     38  * else
     39  * unsigned int(4) reserved;
     40  * unsigned int(16) item_count;
     41  * for (i=0; i<item_count; i++) {
     42  * unsigned int(16) item_ID;
     43  * if (version == 1) {
     44  * unsigned int(12) reserved = 0;
     45  * unsigned int(4) construction_method;
     46  * }
     47  * unsigned int(16) data_reference_index;
     48  * unsigned int(base_offset_size*8) base_offset;
     49  * unsigned int(16) extent_count;
     50  * for (j=0; j<extent_count; j++) {
     51  * if ((version == 1) && (index_size > 0)) {
     52  * unsigned int(index_size*8) extent_index;
     53  * }
     54  * unsigned int(offset_size*8) extent_offset;
     55  * unsigned int(length_size*8) extent_length;
     56  * }
     57  * }
     58  * }
     59  */
     60 public class ItemLocationBox extends AbstractFullBox {
     61     public int offsetSize = 8;
     62     public int lengthSize = 8;
     63     public int baseOffsetSize = 8;
     64     public int indexSize = 0;
     65     public List<Item> items = new LinkedList<Item>();
     66 
     67     public static final String TYPE = "iloc";
     68 
     69     public ItemLocationBox() {
     70         super(TYPE);
     71     }
     72 
     73     @Override
     74     protected long getContentSize() {
     75         long size = 8;
     76         for (Item item : items) {
     77             size += item.getSize();
     78         }
     79         return size;
     80     }
     81 
     82 
     83     @Override
     84     protected void getContent(ByteBuffer byteBuffer) {
     85         writeVersionAndFlags(byteBuffer);
     86         IsoTypeWriter.writeUInt8(byteBuffer, ((offsetSize << 4) | lengthSize));
     87         if (getVersion() == 1) {
     88             IsoTypeWriter.writeUInt8(byteBuffer, (baseOffsetSize << 4 | indexSize));
     89         } else {
     90             IsoTypeWriter.writeUInt8(byteBuffer, (baseOffsetSize << 4));
     91         }
     92         IsoTypeWriter.writeUInt16(byteBuffer, items.size());
     93         for (Item item : items) {
     94             item.getContent(byteBuffer);
     95         }
     96     }
     97 
     98     @Override
     99     public void _parseDetails(ByteBuffer content) {
    100         parseVersionAndFlags(content);
    101         int tmp = IsoTypeReader.readUInt8(content);
    102         offsetSize = tmp >>> 4;
    103         lengthSize = tmp & 0xf;
    104         tmp = IsoTypeReader.readUInt8(content);
    105         baseOffsetSize = tmp >>> 4;
    106 
    107         if (getVersion() == 1) {
    108             indexSize = tmp & 0xf;
    109         }
    110         int itemCount = IsoTypeReader.readUInt16(content);
    111         for (int i = 0; i < itemCount; i++) {
    112             items.add(new Item(content));
    113         }
    114     }
    115 
    116 
    117     public int getOffsetSize() {
    118         return offsetSize;
    119     }
    120 
    121     public void setOffsetSize(int offsetSize) {
    122         this.offsetSize = offsetSize;
    123     }
    124 
    125     public int getLengthSize() {
    126         return lengthSize;
    127     }
    128 
    129     public void setLengthSize(int lengthSize) {
    130         this.lengthSize = lengthSize;
    131     }
    132 
    133     public int getBaseOffsetSize() {
    134         return baseOffsetSize;
    135     }
    136 
    137     public void setBaseOffsetSize(int baseOffsetSize) {
    138         this.baseOffsetSize = baseOffsetSize;
    139     }
    140 
    141     public int getIndexSize() {
    142         return indexSize;
    143     }
    144 
    145     public void setIndexSize(int indexSize) {
    146         this.indexSize = indexSize;
    147     }
    148 
    149     public List<Item> getItems() {
    150         return items;
    151     }
    152 
    153     public void setItems(List<Item> items) {
    154         this.items = items;
    155     }
    156 
    157 
    158     public Item createItem(int itemId, int constructionMethod, int dataReferenceIndex, long baseOffset, List<Extent> extents) {
    159         return new Item(itemId, constructionMethod, dataReferenceIndex, baseOffset, extents);
    160     }
    161 
    162     Item createItem(ByteBuffer bb) {
    163         return new Item(bb);
    164     }
    165 
    166     public class Item {
    167         public int itemId;
    168         public int constructionMethod;
    169         public int dataReferenceIndex;
    170         public long baseOffset;
    171         public List<Extent> extents = new LinkedList<Extent>();
    172 
    173         public Item(ByteBuffer in) {
    174             itemId = IsoTypeReader.readUInt16(in);
    175 
    176             if (getVersion() == 1) {
    177                 int tmp = IsoTypeReader.readUInt16(in);
    178                 constructionMethod = tmp & 0xf;
    179             }
    180 
    181             dataReferenceIndex = IsoTypeReader.readUInt16(in);
    182             if (baseOffsetSize > 0) {
    183                 baseOffset = IsoTypeReaderVariable.read(in, baseOffsetSize);
    184             } else {
    185                 baseOffset = 0;
    186             }
    187             int extentCount = IsoTypeReader.readUInt16(in);
    188 
    189 
    190             for (int i = 0; i < extentCount; i++) {
    191                 extents.add(new Extent(in));
    192             }
    193         }
    194 
    195         public Item(int itemId, int constructionMethod, int dataReferenceIndex, long baseOffset, List<Extent> extents) {
    196             this.itemId = itemId;
    197             this.constructionMethod = constructionMethod;
    198             this.dataReferenceIndex = dataReferenceIndex;
    199             this.baseOffset = baseOffset;
    200             this.extents = extents;
    201         }
    202 
    203         public int getSize() {
    204             int size = 2;
    205 
    206             if (getVersion() == 1) {
    207                 size += 2;
    208             }
    209 
    210             size += 2;
    211             size += baseOffsetSize;
    212             size += 2;
    213 
    214 
    215             for (Extent extent : extents) {
    216                 size += extent.getSize();
    217             }
    218             return size;
    219         }
    220 
    221         public void setBaseOffset(long baseOffset) {
    222             this.baseOffset = baseOffset;
    223         }
    224 
    225         public void getContent(ByteBuffer bb)  {
    226             IsoTypeWriter.writeUInt16(bb, itemId);
    227 
    228             if (getVersion() == 1) {
    229                 IsoTypeWriter.writeUInt16(bb, constructionMethod);
    230             }
    231 
    232 
    233             IsoTypeWriter.writeUInt16(bb, dataReferenceIndex);
    234             if (baseOffsetSize > 0) {
    235                 IsoTypeWriterVariable.write(baseOffset, bb, baseOffsetSize);
    236             }
    237             IsoTypeWriter.writeUInt16(bb, extents.size());
    238 
    239             for (Extent extent : extents) {
    240                 extent.getContent(bb);
    241             }
    242         }
    243 
    244         @Override
    245         public boolean equals(Object o) {
    246             if (this == o) return true;
    247             if (o == null || getClass() != o.getClass()) return false;
    248 
    249             Item item = (Item) o;
    250 
    251             if (baseOffset != item.baseOffset) return false;
    252             if (constructionMethod != item.constructionMethod) return false;
    253             if (dataReferenceIndex != item.dataReferenceIndex) return false;
    254             if (itemId != item.itemId) return false;
    255             if (extents != null ? !extents.equals(item.extents) : item.extents != null) return false;
    256 
    257             return true;
    258         }
    259 
    260         @Override
    261         public int hashCode() {
    262             int result = itemId;
    263             result = 31 * result + constructionMethod;
    264             result = 31 * result + dataReferenceIndex;
    265             result = 31 * result + (int) (baseOffset ^ (baseOffset >>> 32));
    266             result = 31 * result + (extents != null ? extents.hashCode() : 0);
    267             return result;
    268         }
    269 
    270         @Override
    271         public String toString() {
    272             return "Item{" +
    273                     "baseOffset=" + baseOffset +
    274                     ", itemId=" + itemId +
    275                     ", constructionMethod=" + constructionMethod +
    276                     ", dataReferenceIndex=" + dataReferenceIndex +
    277                     ", extents=" + extents +
    278                     '}';
    279         }
    280     }
    281 
    282 
    283     public Extent createExtent(long extentOffset, long extentLength, long extentIndex) {
    284         return new Extent(extentOffset, extentLength, extentIndex);
    285     }
    286 
    287     Extent createExtent(ByteBuffer bb) {
    288         return new Extent(bb);
    289     }
    290 
    291 
    292     public class Extent {
    293         public long extentOffset;
    294         public long extentLength;
    295         public long extentIndex;
    296 
    297         public Extent(long extentOffset, long extentLength, long extentIndex) {
    298             this.extentOffset = extentOffset;
    299             this.extentLength = extentLength;
    300             this.extentIndex = extentIndex;
    301         }
    302 
    303 
    304         public Extent(ByteBuffer in) {
    305             if ((getVersion() == 1) && indexSize > 0) {
    306                 extentIndex = IsoTypeReaderVariable.read(in, indexSize);
    307             }
    308             extentOffset = IsoTypeReaderVariable.read(in, offsetSize);
    309             extentLength = IsoTypeReaderVariable.read(in, lengthSize);
    310         }
    311 
    312         public void getContent(ByteBuffer os)  {
    313             if ((getVersion() == 1) && indexSize > 0) {
    314                 IsoTypeWriterVariable.write(extentIndex, os, indexSize);
    315             }
    316             IsoTypeWriterVariable.write(extentOffset, os, offsetSize);
    317             IsoTypeWriterVariable.write(extentLength, os, lengthSize);
    318         }
    319 
    320         public int getSize() {
    321             return (indexSize > 0 ? indexSize : 0) + offsetSize + lengthSize;
    322         }
    323 
    324 
    325         @Override
    326         public boolean equals(Object o) {
    327             if (this == o) return true;
    328             if (o == null || getClass() != o.getClass()) return false;
    329 
    330             Extent extent = (Extent) o;
    331 
    332             if (extentIndex != extent.extentIndex) return false;
    333             if (extentLength != extent.extentLength) return false;
    334             if (extentOffset != extent.extentOffset) return false;
    335 
    336             return true;
    337         }
    338 
    339         @Override
    340         public int hashCode() {
    341             int result = (int) (extentOffset ^ (extentOffset >>> 32));
    342             result = 31 * result + (int) (extentLength ^ (extentLength >>> 32));
    343             result = 31 * result + (int) (extentIndex ^ (extentIndex >>> 32));
    344             return result;
    345         }
    346 
    347         @Override
    348         public String toString() {
    349             final StringBuilder sb = new StringBuilder();
    350             sb.append("Extent");
    351             sb.append("{extentOffset=").append(extentOffset);
    352             sb.append(", extentLength=").append(extentLength);
    353             sb.append(", extentIndex=").append(extentIndex);
    354             sb.append('}');
    355             return sb.toString();
    356         }
    357     }
    358 
    359 
    360 }
    361