blob: 6dcee6fa1f54be19ba4fdb0e876726e59d14f2e1 [file] [log] [blame]
/*
* 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();
}
}
}