/***************************************
* 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.util.*;
/** Indexes within a Group of Pictures. */
public class GroupOfPicturesIndex
{
private Vector codingOrderIndex = null;
private Vector displayOrderIndex = null;
private boolean displayOrderIndexed = false;
public GroupOfPicturesIndex()
{
codingOrderIndex = new Vector();
}
/**
* Adds a <code>GroupOfPicturesIndexElement</code>, which
* represents one picture (frame) in the Group of Pictures, to
* the index.
* @param startPosition the start position
* @param dataSize the data length
* @param type
* @param displayOrder
*/
public void addPicture(long startPosition, long dataSize, byte type, int displayOrder)
{
codingOrderIndex.add(new GroupOfPicturesIndexElement(startPosition, dataSize, type, displayOrder));
displayOrderIndexed = false;
}
/**
* @param n the frame
* @return the byte position (in the video stream) of the
* (zero-based) <code>n</code>th picture (frame) in this Group
* Of Pictures (in display order).
* @throws FrameNotFoundException
*/
public long getPositionOfPicture(int n) throws FrameNotFoundException
{
try
{
return ((GroupOfPicturesIndexElement)getElementsInDisplayOrder().elementAt(n)).getStartPosition();
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new FrameNotFoundException("Picture " + n + " not in " + this);
}
}
public int getLastIOrPPicture(int n) throws FrameNotFoundException
{
Vector codingOrder = getElementsInCodingOrder();
int codingOrderIndex = mapDisplayOrderToCodingOrder(n);
for (int i = codingOrderIndex-1; i >= 0; i--)
{
switch (((GroupOfPicturesIndexElement)codingOrder.elementAt(i)).getType())
{
case PictureCodingTypes.TYPE_I:
case PictureCodingTypes.TYPE_P: return mapCodingOrderToDisplayOrder(i);
}
}
throw new FrameNotFoundException();
}
public int getLastIOrPPicture() throws FrameNotFoundException
{
Vector codingOrder = getElementsInCodingOrder();
for (int i = codingOrder.size()-1; i >= 0; i--)
{
switch (((GroupOfPicturesIndexElement)codingOrder.elementAt(i)).getType())
{
case PictureCodingTypes.TYPE_I:
case PictureCodingTypes.TYPE_P: return mapCodingOrderToDisplayOrder(i);
}
}
throw new FrameNotFoundException();
}
public long getPositionOfPictureInCodingOrder(int n) throws FrameNotFoundException
{
try
{
return ((GroupOfPicturesIndexElement)getElementsInCodingOrder().elementAt(n)).getStartPosition();
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new FrameNotFoundException();
}
}
/** @return a <code>Vector<code> of <code>GroupOfPicturesIndexElement</code>s in display order. */
public Vector getElementsInDisplayOrder()
{
if (!displayOrderIndexed)
{
displayOrderIndex = (Vector)codingOrderIndex.clone();
Collections.sort(displayOrderIndex);
displayOrderIndexed = true;
}
return displayOrderIndex;
}
/** @return a <code>Vector<code> of <code>GroupOfPicturesIndexElement</code>s in coding order. */
public Vector getElementsInCodingOrder()
{
return codingOrderIndex;
}
/**
* Maps a (0-based) frame in dislay order to a (0-based) frame in coding order.
* @param displayOrder
* @return
* @throws FrameNotFoundException
*/
public int mapDisplayOrderToCodingOrder(int displayOrder) throws FrameNotFoundException
{
int i = codingOrderIndex.indexOf(getElementsInDisplayOrder().elementAt(displayOrder));
if (i == -1)
throw new FrameNotFoundException();
return i;
}
/**
* Maps a (0-based) frame in coding order to a (0-based) frame in display order.
* @param codingOrder
* @return
* @throws FrameNotFoundException
*/
public int mapCodingOrderToDisplayOrder(int codingOrder) throws FrameNotFoundException
{
int i = getElementsInDisplayOrder().indexOf(codingOrderIndex.elementAt(codingOrder));
if (i == -1)
throw new FrameNotFoundException();
return i;
}
/**
* Returns the type of the (0-based) frame in coding order.
* @param n
* @return
* @throws FrameNotFoundException
*/
public byte getTypeOfPictureInCodingOrder(int n) throws FrameNotFoundException
{
return ((GroupOfPicturesIndexElement)codingOrderIndex.elementAt(n)).getType();
}
public byte getTypeOfPicture(int n) throws FrameNotFoundException
{
return ((GroupOfPicturesIndexElement)getElementsInDisplayOrder().elementAt(n)).getType();
}
public String toString()
{
return "(" + codingOrderIndex + ")";
}
}