/***************************************
* ViPER-MPEG *
* The Video Processing *
* Evaluation Resource *
* MPEG-1 Decoder *
* Distributed under the LGPL license *
* Terms available at gnu.org. *
* *
* Copyright University of Maryland, *
* College Park. *
***************************************/
package edu.umd.cfar.lamp.mpeg1.video;
import java.io.*;
import edu.columbia.ee.flavor.*;
import edu.umd.cfar.lamp.mpeg1.*;
/** Represents one Group of Pictures within a <code>VideoIndex</code>. */
public class VideoIndexElement implements Comparable
{
private long startPosition;
private int startPicture;
private int numPictures;
private int sequenceHeader;
private VideoIndex videoIndex;
private GroupOfPicturesIndex gopIndex = null;
public VideoIndexElement(long startPosition, int startPicture, int numPictures, int sequenceHeader, VideoIndex videoIndex) throws IOException, MpegException
{
this.startPosition = startPosition;
this.startPicture = startPicture;
this.numPictures = numPictures;
this.sequenceHeader = sequenceHeader;
this.videoIndex = videoIndex;
}
public void writeIndex(DataOutput out) throws IOException
{
out.writeLong(startPosition);
out.writeInt(numPictures);
out.writeInt(sequenceHeader);
}
public int compareTo(Object o)
{
VideoIndexElement other = (VideoIndexElement)o;
if (getStartPosition() < other.getStartPosition())
return -1;
if (getStartPosition() > other.getStartPosition())
return 1;
return 0;
}
public boolean containsPicture(int picture)
{
return (findPicture(picture) == 0);
}
public int findPicture(int picture)
{
if (picture < getStartPicture())
return -1;
if (picture > getLastPicture())
return 1;
return 0;
}
public String toString()
{
return "(Position: " + startPosition + ", First Picture: " + startPicture + ", Number of Pictures: " + numPictures + ")";
}
public long getStartPosition()
{
return startPosition;
}
public int getStartPicture()
{
return startPicture;
}
public int getNumPictures()
{
return numPictures;
}
public int getLastPicture()
{
return startPicture + numPictures - 1;
}
public int getSequenceHeader()
{
return sequenceHeader;
}
public boolean gopIndexed()
{
return (gopIndex != null);
}
public void indexGop() throws IOException, MpegException
{
if (!gopIndexed())
{
gopIndex = new GroupOfPicturesIndex();
VideoSource videoSource = videoIndex.getVideoSource().copySource();
videoSource.seek(startPosition);
GroupOfPictures.index(new Bitstream(videoSource), videoIndex.getIndexerState(), gopIndex);
videoSource.close();
}
}
/**
* @param n the frame
* @return the byte position (in the video stream) of the
* (zero-based) <code>n</code>th picture (frame).
* @throws IOException
* @throws MpegException
*/
public long getPositionOfPicture(int n) throws IOException, MpegException
{
if (!containsPicture(n))
throw new FrameNotFoundException("Frame " + n + " not in " + this);
indexGop();
return gopIndex.getPositionOfPicture(n - getStartPicture()) + getStartPosition();
}
public int getLastIOrPPicture(int n) throws IOException, MpegException
{
int comparison = findPicture(n);
if (comparison < 0)
throw new FrameNotFoundException("Searching the wrong VideoIndexElement.");
indexGop();
if (comparison > 0)
return gopIndex.getLastIOrPPicture() + getStartPicture();
else
return gopIndex.getLastIOrPPicture(n - getStartPicture()) + getStartPicture();
}
public byte getPictureCodingTypeOfPicture(int n) throws IOException, MpegException
{
if (!containsPicture(n))
throw new FrameNotFoundException();
indexGop();
return gopIndex.getTypeOfPicture(n - getStartPicture());
}
}