package com.castlabs.dash.dashfragmenter.representation;
import com.coremedia.iso.boxes.Box;
import com.coremedia.iso.boxes.Container;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.googlecode.mp4parser.util.CastUtils.l2i;
/**
* Created by sannies on 15.06.2015.
*/
public class ListContainer implements Container {
List<Box> boxes = Collections.emptyList();
public ListContainer(List<Box> boxes) {
this.boxes = boxes;
}
public List<Box> getBoxes() {
return boxes;
}
public void setBoxes(List<Box> boxes) {
this.boxes = boxes;
}
public <T extends Box> List<T> getBoxes(Class<T> clazz) {
List<T> boxesToBeReturned = null;
T oneBox = null;
List<Box> boxes = getBoxes();
for (Box boxe : boxes) {
//clazz.isInstance(boxe) / clazz == boxe.getClass()?
// I hereby finally decide to use isInstance
if (clazz.isInstance(boxe)) {
if (oneBox == null) {
oneBox = (T) boxe;
} else {
if (boxesToBeReturned == null) {
boxesToBeReturned = new ArrayList<T>(2);
boxesToBeReturned.add(oneBox);
}
boxesToBeReturned.add((T) boxe);
}
}
}
if (boxesToBeReturned != null) {
return boxesToBeReturned;
} else if (oneBox != null) {
return Collections.singletonList(oneBox);
} else {
return Collections.emptyList();
}
}
public <T extends Box> List<T> getBoxes(Class<T> clazz, boolean recursive) {
List<T> boxesToBeReturned = new ArrayList<T>(2);
List<Box> boxes = getBoxes();
for (Box boxe : boxes) {
//clazz.isInstance(boxe) / clazz == boxe.getClass()?
// I hereby finally decide to use isInstance
if (clazz.isInstance(boxe)) {
boxesToBeReturned.add((T) boxe);
}
if (recursive && boxe instanceof Container) {
boxesToBeReturned.addAll(((Container) boxe).getBoxes(clazz, recursive));
}
}
return boxesToBeReturned;
}
public ByteBuffer getByteBuffer(long rangeStart, long size) throws IOException {
ByteBuffer out = ByteBuffer.allocate(l2i(size));
long rangeEnd = rangeStart + size;
long boxStart;
long boxEnd = 0;
for (Box box : boxes) {
boxStart = boxEnd;
boxEnd = boxStart + box.getSize();
if (!(boxEnd <= rangeStart || boxStart >= rangeEnd)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
WritableByteChannel wbc = Channels.newChannel(baos);
box.getBox(wbc);
wbc.close();
if (boxStart >= rangeStart && boxEnd <= rangeEnd) {
out.put(baos.toByteArray());
// within -> use full box
} else if (boxStart < rangeStart && boxEnd > rangeEnd) {
// around -> use 'middle' of box
int length = l2i(box.getSize() - (rangeStart - boxStart) - (boxEnd - rangeEnd));
out.put(baos.toByteArray(), l2i(rangeStart - boxStart), length);
} else if (boxStart < rangeStart && boxEnd <= rangeEnd) {
// endwith
int length = l2i(box.getSize() - (rangeStart - boxStart));
out.put(baos.toByteArray(), l2i(rangeStart - boxStart), length);
} else if (boxStart >= rangeStart && boxEnd > rangeEnd) {
int length = l2i(box.getSize() - (boxEnd - rangeEnd));
out.put(baos.toByteArray(), 0, length);
}
}
}
return (ByteBuffer) out.rewind();
}
public void writeContainer(WritableByteChannel bb) throws IOException {
for (Box box : boxes) {
box.getBox(bb);
}
}
}