package org.jcodec.containers.mps.index;
import org.jcodec.common.RunLength;
import java.nio.ByteBuffer;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Represents index for MPEG PS stream, enables demuxers to do precise seek
*
* @author The JCodec project
*
*/
public class MPSIndex {
protected long[] pesTokens;
protected RunLength.Integer pesStreamIds;
protected MPSStreamIndex[] streams;
public static class MPSStreamIndex {
protected int streamId;
protected int[] fsizes;
protected int[] fpts;
protected int[] fdur;
protected int[] sync;
public MPSStreamIndex(int streamId, int[] fsizes, int[] fpts, int[] fdur, int[] sync) {
this.streamId = streamId;
this.fsizes = fsizes;
this.fpts = fpts;
this.fdur = fdur;
this.sync = sync;
}
public int getStreamId() {
return streamId;
}
public int[] getFsizes() {
return fsizes;
}
public int[] getFpts() {
return fpts;
}
public int[] getFdur() {
return fdur;
}
public int[] getSync() {
return sync;
}
public static MPSStreamIndex parseIndex(ByteBuffer index) {
int streamId = index.get() & 0xff;
int fCnt = index.getInt();
int[] fsizes = new int[fCnt];
for (int i = 0; i < fCnt; i++) {
fsizes[i] = index.getInt();
}
int fptsCnt = index.getInt();
int[] fpts = new int[fptsCnt];
for (int i = 0; i < fptsCnt; i++) {
fpts[i] = index.getInt();
}
int fdurCnt = index.getInt();
int[] fdur = new int[fdurCnt];
for (int i = 0; i < fdurCnt; i++) {
fdur[i] = index.getInt();
}
int syncCount = index.getInt();
int[] sync = new int[syncCount];
for (int i = 0; i < syncCount; i++)
sync[i] = index.getInt();
return new MPSStreamIndex(streamId, fsizes, fpts, fdur, sync);
}
public void serialize(ByteBuffer index) {
index.put((byte) streamId);
index.putInt(fsizes.length);
for (int i = 0; i < fsizes.length; i++)
index.putInt(fsizes[i]);
index.putInt(fpts.length);
for (int i = 0; i < fpts.length; i++)
index.putInt(fpts[i]);
index.putInt(fdur.length);
for (int i = 0; i < fdur.length; i++)
index.putInt(fdur[i]);
index.putInt(sync.length);
for (int i = 0; i < sync.length; i++)
index.putInt(sync[i]);
}
public int estimateSize() {
return (fpts.length << 2) + (fdur.length << 2) + (sync.length << 2) + (fsizes.length << 2) + 64;
}
}
public MPSIndex(long[] pesTokens, RunLength.Integer pesStreamIds, MPSStreamIndex[] streams) {
this.pesTokens = pesTokens;
this.pesStreamIds = pesStreamIds;
this.streams = streams;
}
public long[] getPesTokens() {
return pesTokens;
}
public RunLength.Integer getPesStreamIds() {
return pesStreamIds;
}
public MPSStreamIndex[] getStreams() {
return streams;
}
public static MPSIndex parseIndex(ByteBuffer index) {
int pesCnt = index.getInt();
long[] pesTokens = new long[pesCnt];
for (int i = 0; i < pesCnt; i++) {
pesTokens[i] = index.getLong();
}
RunLength.Integer pesStreamId = RunLength.Integer.parse(index);
int nStreams = index.getInt();
MPSStreamIndex[] streams = new MPSStreamIndex[nStreams];
for (int i = 0; i < nStreams; i++) {
streams[i] = MPSStreamIndex.parseIndex(index);
}
return new MPSIndex(pesTokens, pesStreamId, streams);
}
public void serializeTo(ByteBuffer index) {
index.putInt(pesTokens.length);
for (int i = 0; i < pesTokens.length; i++) {
index.putLong(pesTokens[i]);
}
pesStreamIds.serialize(index);
index.putInt(streams.length);
for (MPSStreamIndex mpsStreamIndex : streams) {
mpsStreamIndex.serialize(index);
}
}
public int estimateSize() {
int size = (pesTokens.length << 3) + pesStreamIds.estimateSize();
for (MPSStreamIndex mpsStreamIndex : streams) {
size += mpsStreamIndex.estimateSize();
}
return size + 64;
}
public static long makePESToken(long leading, long pesLen, long payloadLen) {
return (leading << 48) | (pesLen << 24) | payloadLen;
}
public static int leadingSize(long token) {
return (int) (token >> 48) & 0xffff;
}
public static int pesLen(long token) {
return (int) (token >> 24) & 0xffffff;
}
public static int payLoadSize(long token) {
return (int) token & 0xffffff;
}
}