/* * @(#)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; } }