/* * Copyright 2008 CoreMedia AG, Hamburg * * 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.coremedia.iso.boxes; import com.coremedia.iso.IsoTypeReader; import com.coremedia.iso.IsoTypeReaderVariable; import com.coremedia.iso.IsoTypeWriter; import com.coremedia.iso.IsoTypeWriterVariable; import com.googlecode.mp4parser.AbstractFullBox; import java.io.IOException; import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.List; /** * aligned(8) class ItemLocationBox extends FullBox(‘iloc’, version, 0) { * unsigned int(4) offset_size; * unsigned int(4) length_size; * unsigned int(4) base_offset_size; * if (version == 1) * unsigned int(4) index_size; * else * unsigned int(4) reserved; * unsigned int(16) item_count; * for (i=0; i<item_count; i++) { * unsigned int(16) item_ID; * if (version == 1) { * unsigned int(12) reserved = 0; * unsigned int(4) construction_method; * } * unsigned int(16) data_reference_index; * unsigned int(base_offset_size*8) base_offset; * unsigned int(16) extent_count; * for (j=0; j<extent_count; j++) { * if ((version == 1) && (index_size > 0)) { * unsigned int(index_size*8) extent_index; * } * unsigned int(offset_size*8) extent_offset; * unsigned int(length_size*8) extent_length; * } * } * } */ public class ItemLocationBox extends AbstractFullBox { public int offsetSize = 8; public int lengthSize = 8; public int baseOffsetSize = 8; public int indexSize = 0; public List<Item> items = new LinkedList<Item>(); public static final String TYPE = "iloc"; public ItemLocationBox() { super(TYPE); } @Override protected long getContentSize() { long size = 8; for (Item item : items) { size += item.getSize(); } return size; } @Override protected void getContent(ByteBuffer byteBuffer) { writeVersionAndFlags(byteBuffer); IsoTypeWriter.writeUInt8(byteBuffer, ((offsetSize << 4) | lengthSize)); if (getVersion() == 1) { IsoTypeWriter.writeUInt8(byteBuffer, (baseOffsetSize << 4 | indexSize)); } else { IsoTypeWriter.writeUInt8(byteBuffer, (baseOffsetSize << 4)); } IsoTypeWriter.writeUInt16(byteBuffer, items.size()); for (Item item : items) { item.getContent(byteBuffer); } } @Override public void _parseDetails(ByteBuffer content) { parseVersionAndFlags(content); int tmp = IsoTypeReader.readUInt8(content); offsetSize = tmp >>> 4; lengthSize = tmp & 0xf; tmp = IsoTypeReader.readUInt8(content); baseOffsetSize = tmp >>> 4; if (getVersion() == 1) { indexSize = tmp & 0xf; } int itemCount = IsoTypeReader.readUInt16(content); for (int i = 0; i < itemCount; i++) { items.add(new Item(content)); } } public int getOffsetSize() { return offsetSize; } public void setOffsetSize(int offsetSize) { this.offsetSize = offsetSize; } public int getLengthSize() { return lengthSize; } public void setLengthSize(int lengthSize) { this.lengthSize = lengthSize; } public int getBaseOffsetSize() { return baseOffsetSize; } public void setBaseOffsetSize(int baseOffsetSize) { this.baseOffsetSize = baseOffsetSize; } public int getIndexSize() { return indexSize; } public void setIndexSize(int indexSize) { this.indexSize = indexSize; } public List<Item> getItems() { return items; } public void setItems(List<Item> items) { this.items = items; } public Item createItem(int itemId, int constructionMethod, int dataReferenceIndex, long baseOffset, List<Extent> extents) { return new Item(itemId, constructionMethod, dataReferenceIndex, baseOffset, extents); } Item createItem(ByteBuffer bb) { return new Item(bb); } public class Item { public int itemId; public int constructionMethod; public int dataReferenceIndex; public long baseOffset; public List<Extent> extents = new LinkedList<Extent>(); public Item(ByteBuffer in) { itemId = IsoTypeReader.readUInt16(in); if (getVersion() == 1) { int tmp = IsoTypeReader.readUInt16(in); constructionMethod = tmp & 0xf; } dataReferenceIndex = IsoTypeReader.readUInt16(in); if (baseOffsetSize > 0) { baseOffset = IsoTypeReaderVariable.read(in, baseOffsetSize); } else { baseOffset = 0; } int extentCount = IsoTypeReader.readUInt16(in); for (int i = 0; i < extentCount; i++) { extents.add(new Extent(in)); } } public Item(int itemId, int constructionMethod, int dataReferenceIndex, long baseOffset, List<Extent> extents) { this.itemId = itemId; this.constructionMethod = constructionMethod; this.dataReferenceIndex = dataReferenceIndex; this.baseOffset = baseOffset; this.extents = extents; } public int getSize() { int size = 2; if (getVersion() == 1) { size += 2; } size += 2; size += baseOffsetSize; size += 2; for (Extent extent : extents) { size += extent.getSize(); } return size; } public void setBaseOffset(long baseOffset) { this.baseOffset = baseOffset; } public void getContent(ByteBuffer bb) { IsoTypeWriter.writeUInt16(bb, itemId); if (getVersion() == 1) { IsoTypeWriter.writeUInt16(bb, constructionMethod); } IsoTypeWriter.writeUInt16(bb, dataReferenceIndex); if (baseOffsetSize > 0) { IsoTypeWriterVariable.write(baseOffset, bb, baseOffsetSize); } IsoTypeWriter.writeUInt16(bb, extents.size()); for (Extent extent : extents) { extent.getContent(bb); } } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Item item = (Item) o; if (baseOffset != item.baseOffset) return false; if (constructionMethod != item.constructionMethod) return false; if (dataReferenceIndex != item.dataReferenceIndex) return false; if (itemId != item.itemId) return false; if (extents != null ? !extents.equals(item.extents) : item.extents != null) return false; return true; } @Override public int hashCode() { int result = itemId; result = 31 * result + constructionMethod; result = 31 * result + dataReferenceIndex; result = 31 * result + (int) (baseOffset ^ (baseOffset >>> 32)); result = 31 * result + (extents != null ? extents.hashCode() : 0); return result; } @Override public String toString() { return "Item{" + "baseOffset=" + baseOffset + ", itemId=" + itemId + ", constructionMethod=" + constructionMethod + ", dataReferenceIndex=" + dataReferenceIndex + ", extents=" + extents + '}'; } } public Extent createExtent(long extentOffset, long extentLength, long extentIndex) { return new Extent(extentOffset, extentLength, extentIndex); } Extent createExtent(ByteBuffer bb) { return new Extent(bb); } public class Extent { public long extentOffset; public long extentLength; public long extentIndex; public Extent(long extentOffset, long extentLength, long extentIndex) { this.extentOffset = extentOffset; this.extentLength = extentLength; this.extentIndex = extentIndex; } public Extent(ByteBuffer in) { if ((getVersion() == 1) && indexSize > 0) { extentIndex = IsoTypeReaderVariable.read(in, indexSize); } extentOffset = IsoTypeReaderVariable.read(in, offsetSize); extentLength = IsoTypeReaderVariable.read(in, lengthSize); } public void getContent(ByteBuffer os) { if ((getVersion() == 1) && indexSize > 0) { IsoTypeWriterVariable.write(extentIndex, os, indexSize); } IsoTypeWriterVariable.write(extentOffset, os, offsetSize); IsoTypeWriterVariable.write(extentLength, os, lengthSize); } public int getSize() { return (indexSize > 0 ? indexSize : 0) + offsetSize + lengthSize; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Extent extent = (Extent) o; if (extentIndex != extent.extentIndex) return false; if (extentLength != extent.extentLength) return false; if (extentOffset != extent.extentOffset) return false; return true; } @Override public int hashCode() { int result = (int) (extentOffset ^ (extentOffset >>> 32)); result = 31 * result + (int) (extentLength ^ (extentLength >>> 32)); result = 31 * result + (int) (extentIndex ^ (extentIndex >>> 32)); return result; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("Extent"); sb.append("{extentOffset=").append(extentOffset); sb.append(", extentLength=").append(extentLength); sb.append(", extentIndex=").append(extentIndex); sb.append('}'); return sb.toString(); } } }