/*
* @(#)FramePositioningAdapter.java 1.5 02/08/21
*
* Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved.
*/
package com.sun.media.controls;
import java.awt.Component;
import javax.media.Time;
import javax.media.Track;
import javax.media.Player;
import javax.media.control.FramePositioningControl;
import javax.media.Format;
import javax.media.format.VideoFormat;
import com.sun.media.Reparentable;
/**
* The <code>FramePositioningControl</code> is the interface to control
* precise positioning to a video frame for <code>Players</code>
* and <code>Processors</code>.
*/
public class FramePositioningAdapter implements FramePositioningControl, Reparentable {
static public Track getMasterTrack(Track tracks[]) {
Track master = null;
Format f;
float rate = Format.NOT_SPECIFIED;
for (int i = 0; i < tracks.length; i++) {
if (tracks[i] == null || ((f = tracks[i].getFormat()) == null))
continue;
if (!(f instanceof VideoFormat))
continue;
master = tracks[i];
if ((rate = ((VideoFormat)f).getFrameRate()) != Format.NOT_SPECIFIED &&
rate != 0f) {
return master;
}
}
if (master != null &&
master.mapTimeToFrame(new Time(0)) != FramePositioningControl.FRAME_UNKNOWN)
return master;
else
return null;
}
Object owner;
Player player;
Track master = null;
long frameStep = -1;
public FramePositioningAdapter(Player p, Track track) {
this.player = p;
this.master = track;
// Base on the frame rate, compute the inter-frame duration.
// This is not very accurate since the frame rate reported is not
// very accurate anyway.
Format f = track.getFormat();
if (f instanceof VideoFormat) {
float rate = ((VideoFormat)f).getFrameRate();
if (rate != Format.NOT_SPECIFIED && rate != 0f)
frameStep = (long)(Time.ONE_SECOND / rate);
}
}
/**
* Seek to a given video frame.
* @param frameNumber the frame to seek to.
* @return the actual frame that the Player has seeked to.
*/
public int seek(int frameNumber) {
Time seekTo = master.mapFrameToTime(frameNumber);
if (seekTo != null && seekTo != FramePositioningControl.TIME_UNKNOWN) {
player.setMediaTime(seekTo);
return master.mapTimeToFrame(seekTo);
} else {
// Can't do any thing if mapFrameToTime fails.
return FramePositioningControl.FRAME_UNKNOWN;
}
}
/**
* Skip a given number of frames from the current position.
* @param framesToSkip the number of frames to skip from the current
* position. If framesToSkip is positive, it will seek forward
* by framesToSkip number of frames. If framesToSkip is negative,
* it will seek backward by framesToSkip number of frames.
* e.g. skip(-1) will step backward one frame.
* @return the actual number of frames skipped.
*/
public int skip(int framesToSkip) {
if (frameStep != -1) {
// Use interframe duration.
long t = player.getMediaNanoseconds() + (framesToSkip * frameStep);
player.setMediaTime(new Time(t));
return framesToSkip;
} else {
int currentFrame = master.mapTimeToFrame(player.getMediaTime());
if (currentFrame != 0 &&
currentFrame != FramePositioningControl.FRAME_UNKNOWN) {
int newFrame = seek(currentFrame+framesToSkip);
return newFrame - currentFrame;
} else {
// Ran out of options.
return FramePositioningControl.FRAME_UNKNOWN;
}
}
}
/**
* Converts the given frame number to the corresponding media time.
* <p>
* @param frameNumber the input frame number for the conversion.
* @return the converted media time for the given frame. If the
* conversion fails, TIME_UNKNOWN is returned.
*/
public Time mapFrameToTime(int frameNumber) {
return master.mapFrameToTime(frameNumber);
}
/**
* Converts the given media time to the corresponding frame number.
* <p>
* The frame returned is the nearest frame that has a media time
* less than or equal to the given media time.
* <p>
* @param mediaTime the input media time for the conversion.
* @return the converted frame number the given media time. If the
* conversion fails, FRAME_UNKNOWN is returned.
*/
public int mapTimeToFrame(Time mediaTime) {
return master.mapTimeToFrame(mediaTime);
}
public Component getControlComponent() {
return null;
}
public Object getOwner() {
if (owner == null)
return this;
else
return owner;
}
public void setOwner(Object newOwner) {
owner = newOwner;
}
}
|