/*
* Copyright (c) 2009 Levente Farkas
* Copyright (c) 2007 Wayne Meissner
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
* 2000 Wim Taymans <wtay@chello.be>
* 2004 Wim Taymans <wim@fluendo.com>
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gstreamer;
import org.gstreamer.lowlevel.GstClockAPI;
import org.gstreamer.lowlevel.GstNative;
/**
* Abstract class for global clocks.
* <p>
* GStreamer uses a global clock to synchronize the plugins in a pipeline.
* Different clock implementations are possible by implementing this abstract
* base class.
* <p>
* The {@link Clock} returns a monotonically increasing time with the method
* gst_clock_get_time(). Its accuracy and base time depend on the specific
* clock implementation but time is always expressed in nanoseconds. Since the
* baseline of the clock is undefined, the clock time returned is not
* meaningful in itself, what matters are the deltas between two clock times.
* The time returned by a clock is called the absolute time.
* <p>
* The pipeline uses the clock to calculate the stream time. Usually all
* renderers synchronize to the global clock using the buffer timestamps, the
* newsegment events and the element's base time, see #GstPipeline.
* <p>
* A clock implementation can support periodic and single shot clock
* notifications both synchronous and asynchronous.
* <p>
* One first needs to create a {@link ClockID} for the periodic or single shot
* notification using {@link #newSingleShotID} or {@link #newPeriodicID}.
* <p>
* To perform a blocking wait for the specific time of the {@link ClockID} use the
* gst_clock_id_wait(). To receive a callback when the specific time is reached
* in the clock use gst_clock_id_wait_async(). Both these calls can be
* interrupted with the gst_clock_id_unschedule() call. If the blocking wait is
* unscheduled a return value of GST_CLOCK_UNSCHEDULED is returned.
* <p>
* Periodic callbacks scheduled async will be repeatedly called automatically
* until it is unscheduled. To schedule a sync periodic callback,
* gst_clock_id_wait() should be called repeatedly.
* <p>
* The async callbacks can happen from any thread, either provided by the core
* or from a streaming thread. The application should be prepared for this.
* <p>
* A {@link ClockID} that has been unscheduled cannot be used again for any wait
* operation, a new ClockID should be created.
* <p>
* It is possible to perform a blocking wait on the same ClockID from
* multiple threads. However, registering the same ClockID for multiple
* async notifications is not possible, the callback will only be called for
* the thread registering the entry last.
* <p>
* These clock operations do not operate on the stream time, so the callbacks
* will also occur when not in {@link State#PLAYING} state as if the clock just keeps on
* running. Some clocks however do not progress when the element that provided
* the clock is not {@link State#PLAYING}.
* <p>
* When a clock has the GST_CLOCK_FLAG_CAN_SET_MASTER flag set, it can be
* slaved to another #GstClock with the gst_clock_set_master(). The clock will
* then automatically be synchronized to this master clock by repeatedly
* sampling the master clock and the slave clock and recalibrating the slave
* clock with {@link #setCalibration}. This feature is mostly useful for
* plugins that have an internal clock but must operate with another clock
* selected by the {@link Pipeline}. They can track the offset and rate difference
* of their internal clock relative to the master clock by using the
* gst_clock_get_calibration() function.
* <p>
* The master/slave synchronisation can be tuned with the "timeout", "window-size"
* and "window-threshold" properties. The "timeout" property defines the interval
* to sample the master clock and run the calibration functions.
* "window-size" defines the number of samples to use when calibrating and
* "window-threshold" defines the minimum number of samples before the
* calibration is performed.
*/
public class Clock extends GstObject {
public static final String GTYPE_NAME = "GstClock";
private static final GstClockAPI gst = GstNative.load(GstClockAPI.class);
public Clock(Initializer init) {
super(init);
}
/**
* Sets the accuracy of the clock.
* <p>
* Some clocks have the possibility to operate with different accuracy at
* the expense of more resource usage. There is normally no need to change
* the default resolution of a clock. The resolution of a clock can only be
* changed if the clock has the GST_CLOCK_FLAG_CAN_SET_RESOLUTION flag set.
*
* @param resolution the new resolution of the clock.
* @return the new resolution of the clock.
*/
public ClockTime setResolution(ClockTime resolution) {
return gst.gst_clock_set_resolution(this, resolution);
}
/**
* Gets the accuracy of the clock. The accuracy of the clock is the granularity
* of the values returned by {@link #getTime}.
*
* @return the resolution of the clock in nanoseconds.
*/
public ClockTime getResolution() {
return gst.gst_clock_get_resolution(this);
}
/**
* Gets the current time of the given clock. The time is always
* monotonically increasing and adjusted according to the current
* offset and rate.
*
* Returns: the time of the clock. Or GST_CLOCK_TIME_NONE when
* giving wrong input.
* @return the time of the clock. Or {@link ClockTime#NONE} when
* given incorrect input.
*/
public ClockTime getTime() {
return gst.gst_clock_get_time(this);
}
/**
* Gets the current internal time of this clock. The time is returned
* unadjusted for the offset and the rate.
*
* Thread safe.
*
* @return the internal time of the clock. Or {@link ClockTime#NONE} when given wrong input.
*/
public ClockTime getInternalTime() {
return gst.gst_clock_get_internal_time(this);
}
/**
* Gets the master clock that this clock is slaved to or null when the clock is
* not slaved to any master clock.
*
* @return A master Clock or null when this clock is not slaved to a master
* clock.
*/
public Clock getMaster() {
return gst.gst_clock_get_master(this);
}
/**
* Set master as the master clock for this clock. This clock will be automatically
* calibrated so that {@link #getTime} reports the same time as the
* master clock.
*
* A clock provider that slaves its clock to a master can get the current
* calibration values with {@link #getCalibration}.
*
* master can be null in which case clock will not be slaved anymore. It will
* however keep reporting its time adjusted with the last configured rate
* and time offsets.
*
* @param master a master Clock
* @return true if the clock is capable of being slaved to a master clock.
* Trying to set a master on a clock without the CAN_SET_MASTER flag will make
* this function return false.
*/
public boolean setMaster(Clock master) {
return gst.gst_clock_set_master(this, master);
}
/**
* Gets the internal rate and reference time of clock. See {@link #setCalibration} for more information.
* <p>
* internal, external, rate_num, and rate_denom can be left NULL if the caller is not interested in the values.
*
* Thread safe.
* @param internal a reference internal time
* @param external a reference external time
* @param rateNumerator the numerator of the rate of the clock relative to its internal time
* @param rateDenominator the denominator of the rate of the clock
*/
public void getCalibration(ClockTime internal, ClockTime external, ClockTime rateNumerator, ClockTime rateDenominator) {
gst.gst_clock_set_calibration(this, internal, external, rateNumerator, rateDenominator);
}
/**
* Adjusts the rate and time of this clock. A rate of 1/1 is the normal speed of
* the clock. Values bigger than 1/1 make the clock go faster.
* <p>
* internal and external are calibration parameters that arrange that
* {@link #getTime} should have been external at internal time internal.
* This internal time should not be in the future; that is, it should be less
* than the value of {@link #getInternalTime} when this function is called.
* <p>
* Subsequent calls to gst_clock_get_time() will return clock times computed as
* follows:
* <p>
* <code>
* time = (internal_time - internal) * rateNumerator/ rateDenominator + external
* </code>
* <p>
* This formula is implemented in gst_clock_adjust_unlocked(). Of course, it
* tries to do the integer arithmetic as precisely as possible.
* <p>
* Note that {@link #getTime} always returns increasing values so when you
* move the clock backwards, getTime() will report the previous value
* until the clock catches up.
*
* Thread safe.
* @param internal a reference internal time
* @param external a reference external time
* @param rateNumerator the numerator of the rate of the clock relative to its internal time
* @param rateDenominator the denominator of the rate of the clock
*/
public void setCalibration(ClockTime internal, ClockTime external, ClockTime rateNumerator, ClockTime rateDenominator) {
gst.gst_clock_set_calibration(this, internal, external, rateNumerator, rateDenominator);
}
/**
* Gets a {@link ClockID} from this clock to trigger a single shot
* notification at the requested time.
* <p>
* Thread safe.
*
* @param time The requested time
* @return A {@link ClockID} that can be used to request the time notification.
*/
public ClockID newSingleShotID(ClockTime time) {
return gst.gst_clock_new_single_shot_id(this, time);
}
/**
* Gets an ID from this clock to trigger a periodic notification.
* The periodeic notifications will be start at time start_time and
* will then be fired with the given interval.
* <p>
* Thread safe.
*
* @param startTime The requested start time.
* @param interval The requested interval.
* @return A {@link ClockID} that can be used to request the time notification.
*/
public ClockID newPeriodicID(ClockTime startTime, ClockTime interval) {
return gst.gst_clock_new_periodic_id(this, startTime, interval);
}
}