package org.jcodec.movtool.streaming; import java.lang.IllegalStateException; import java.lang.System; import java.lang.IllegalArgumentException; import org.jcodec.common.io.NIOUtils; import org.jcodec.platform.BaseInputStream; import java.io.IOException; import java.nio.ByteBuffer; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * Retrieves a movie range * * @author The JCodec project * */ public class MovieRange extends BaseInputStream { private VirtualMovie movie; private long remaining; private int chunkNo; private ByteBuffer chunkData; public MovieRange(VirtualMovie movie, long from, long to) throws IOException { if (to < from) throw new IllegalArgumentException("from < to"); this.movie = movie; MovieSegment chunk = movie.getPacketAt(from); this.remaining = to - from + 1; if (chunk != null) { chunkData = checkDataLen(chunk.getData(), chunk.getDataLen()); chunkNo = chunk.getNo(); NIOUtils.skip(chunkData, (int) (from - chunk.getPos())); } } static ByteBuffer checkDataLen(ByteBuffer chunkData, int chunkDataLen) throws IOException { if(chunkData == null) { System.err.println("WARN: packet expected data len != actual data len " + chunkDataLen + " != 0" ); return ByteBuffer.allocate(chunkDataLen); } if (chunkData.remaining() != chunkDataLen) { System.err.println("WARN: packet expected data len != actual data len " + chunkDataLen + " != " + chunkData.remaining()); chunkDataLen = Math.max(0, chunkDataLen); if (chunkDataLen < chunkData.remaining() || chunkData.capacity() - chunkData.position() >= chunkDataLen) { chunkData.limit(chunkData.position() + chunkDataLen); } else { ByteBuffer correct = ByteBuffer.allocate(chunkDataLen); correct.put(chunkData); correct.clear(); return correct; } } return chunkData; } @Override public int readBuffer(byte[] b, int from, int len) throws IOException { tryFetch(); if (chunkData == null || remaining == 0) return -1; len = (int) Math.min(remaining, len); int totalRead = 0; while (len > 0) { int toRead = Math.min(chunkData.remaining(), len); chunkData.get(b, from, toRead); totalRead += toRead; len -= toRead; from += toRead; tryFetch(); if (chunkData == null) break; } remaining -= totalRead; return totalRead; } private void tryFetch() throws IOException { if (chunkData == null || !chunkData.hasRemaining()) { MovieSegment chunk = movie.getPacketByNo(chunkNo + 1); if (chunk != null) { chunkData = checkDataLen(chunk.getData(), chunk.getDataLen()); chunkNo = chunk.getNo(); } else chunkData = null; } } @Override public int readByte() throws IOException { tryFetch(); if (chunkData == null || remaining == 0) return -1; --remaining; return chunkData.get() & 0xff; } }