All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gstreamer.Pipeline Maven / Gradle / Ivy

There is a newer version: 1.6
Show newest version
/* 
 * Copyright (c) 2007,2008 Wayne Meissner
 * Copyright (C) 1999,2000 Erik Walthinsen 
 *                    2004,2005 Wim Taymans 
 * 
 * This file is part of gstreamer-java.
 *
 * 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 .
 */

package org.gstreamer;
import java.util.concurrent.TimeUnit;

import org.gstreamer.lowlevel.GstElementAPI;
import org.gstreamer.lowlevel.GstNative;
import org.gstreamer.lowlevel.GstParseAPI;
import org.gstreamer.lowlevel.GstPipelineAPI;
import org.gstreamer.lowlevel.GstAPI.GErrorStruct;
import org.gstreamer.lowlevel.annotations.CallerOwnsReturn;

import com.sun.jna.Pointer;
import org.gstreamer.lowlevel.GstQueryAPI;

/**
 * A {@code Pipeline} is a special {@link Bin} used as the toplevel container for
 * the filter graph. The Pipeline will manage the selection and
 * distribution of a global {@link Clock} as well as provide a {@link Bus} to
 * the application. It will also implement a default behavour for managing
 * seek events (see {@link #seek seek}).
 *
 * 

* Elements are added and removed from the pipeline using the {@code Bin} * methods like {@link Bin#add add} and {@link Bin#remove remove}. * *

* Before changing the state of the Pipeline (see {@link Element}) a * {@link Bus} can be retrieved with {@link #getBus getBus}. This bus can then * be used to receive {@link Message}s from the elements in the pipeline. * *

* By default, a Pipeline will automatically flush the pending Bus * messages when going to the NULL state to ensure that no circular * references exist when no messages are read from the Bus. This * behaviour can be changed with {@link #setAutoFlushBus setAutoFlushBus} * *

* When the Pipeline performs the PAUSED to PLAYING state change it will * select a clock for the elements. The clock selection algorithm will by * default select a clock provided by an element that is most upstream * (closest to the source). For live pipelines (ones that return * {@link StateChangeReturn#NO_PREROLL} from the * {@link Element#setState setState} call) this will select the clock provided * by the live source. For normal pipelines this will select a clock provided * by the sinks (most likely the audio sink). If no element provides a clock, * a default SystemClock is used. * *

* The clock selection can be controlled with the gst_pipeline_use_clock() * method, which will enforce a given clock on the pipeline. With * gst_pipeline_auto_clock() the default clock selection algorithm can be * restored. * *

* A Pipeline maintains a stream time for the elements. The stream * time is defined as the difference between the current clock time and * the base time. When the pipeline goes to READY or a flushing seek is * performed on it, the stream time is reset to 0. When the pipeline is * set from PLAYING to PAUSED, the current clock time is sampled and used to * configure the base time for the elements when the pipeline is set * to PLAYING again. This default behaviour can be changed with the * gst_pipeline_set_new_stream_time() method. * * When sending a flushing seek event to a GstPipeline (see * {@link #seek seek}), it will make sure that the pipeline is properly * PAUSED and resumed as well as set the new stream time to 0 when the * seek succeeded. */ public class Pipeline extends Bin { private static interface API extends GstElementAPI, GstPipelineAPI, GstParseAPI { @CallerOwnsReturn Pointer ptr_gst_pipeline_new(String name); } private static final API gst = GstNative.load(API.class); public Pipeline(Initializer init) { super(init); } /** * Creates a new instance of Pipeline with a unique name. */ public Pipeline() { this(initializer(gst.ptr_gst_pipeline_new(null))); initBus(); } /** * Creates a new instance of Pipeline with the given name. * * @param name The name used to identify this pipeline. */ public Pipeline(String name) { this(initializer(gst.ptr_gst_pipeline_new(name))); initBus(); } /** * Creates a pipeline from a text pipeline description. * * This function allows creation of a pipeline based on the syntax used in the * gst-launch utillity. * * @param pipelineDecription the command line describing the pipeline * @return The new Pipeline. */ public static Pipeline launch(String pipelineDecription) { Pointer[] err = { null }; Pipeline pipeline = gst.gst_parse_launch(pipelineDecription, err); if (pipeline == null) { throw new GstException(new GError(new GErrorStruct(err[0]))); } pipeline.initBus(); return pipeline; } /** * Creates a pipeline from a text pipeline description. * * This function allows creation of a pipeline based on the syntax used in the * gst-launch utillity. * * @param pipelineDecription An array of strings containing the command line describing the pipeline. * @return The new Pipeline. */ public static Pipeline launch(String... pipelineDecription) { Pointer[] err = { null }; Pipeline pipeline = gst.gst_parse_launchv(pipelineDecription, err); if (pipeline == null) { throw new GstException(new GError(new GErrorStruct(err[0]))); } pipeline.initBus(); return pipeline; } private void initBus() { Bus bus = getBus(); // // This is mostly a hack to get the Bus to install a sync message handler // bus.setFlushing(true); bus.setFlushing(false); } /** * Sets this pipeline to automatically flush {@link Bus} messages or not. * * @param flush true if automatic flushing is desired, else false. */ public void setAutoFlushBus(boolean flush) { gst.gst_pipeline_set_auto_flush_bus(this, flush); } /** * Checks if the pipeline will automatically flush messages when going to the NULL state. * * @return true if the pipeline automatically flushes messages. */ public boolean getAutoFlushBus() { return gst.gst_pipeline_get_auto_flush_bus(this); } /** * Set the clock for pipeline. * The clock will be distributed to all the elements managed by the pipeline. *

MT safe * * @param clock The {@link Clock} to use * @return true if the clock could be set on the pipeline, false if some * element did not accept the clock. * */ public boolean setClock(Clock clock) { return gst.gst_pipeline_set_clock(this, clock); } /** * Return the current {@link Clock} used by the pipeline. * * @return The {@link Clock} currently in use. */ public Clock getClock() { return gst.gst_pipeline_get_clock(this); } /** * Force the Pipeline to use the a specific clock. * The pipeline will always use the given clock even if new clock * providers are added to this pipeline. *

MT safe * * @param clock The {@link Clock} to use. If clock is null, all clocking is * disabled, and the pipeline will run as fast as possible. * */ public void useClock(Clock clock) { gst.gst_pipeline_use_clock(this, clock); } /** * Gets the {@link Bus} this pipeline uses for messages. * * @return The {@link Bus} that this pipeline uses. */ @Override public Bus getBus() { return gst.gst_pipeline_get_bus(this); } /** * Sets the position in the media stream to time. * * @param time The time to change the position to. * @return true if seek is successful */ public boolean seek(ClockTime time) { return seek(time.convertTo(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS); } /** * Sets the current position in the media stream. * * @param time the time to change the position to. * @param unit the {@code TimeUnit} the time is expressed in. * @return true if seek is successful */ public boolean seek(long time, TimeUnit unit) { return seek(1.0, Format.TIME, SeekFlags.FLUSH | SeekFlags.KEY_UNIT, SeekType.SET, TimeUnit.NANOSECONDS.convert(time, unit), SeekType.NONE, -1); } /** * Seeks to a new position in the media stream. * *

* The start and stop values are expressed in format. *

* A rate of 1.0 means normal playback rate, 2.0 means double speed. * Negative values means backwards playback. A value of 0.0 for the * rate is not allowed and should be accomplished instead by PAUSING the * pipeline. *

* A pipeline has a default playback segment configured with a start * position of 0, a stop position of -1 and a rate of 1.0. The currently * configured playback segment can be queried with #GST_QUERY_SEGMENT. *

* and stopType specify how to adjust the currently configured * start and stop fields in segment. Adjustments can be made relative or * absolute to the last configured values. A type of {@link SeekType#NONE} means * that the position should not be updated. *

* When the rate is positive and start has been updated, playback will start * from the newly configured start position. *

* For negative rates, playback will start from the newly configured stop * position (if any). If the stop position if updated, it must be different from * -1 for negative rates. *

* It is not possible to seek relative to the current playback position, to do * this, PAUSE the pipeline, query the current playback position with * {@link org.gstreamer.Pipeline#queryPosition queryPosition} and update the playback segment * current position with a {@link SeekType#SET} to the desired position. * * @param rate the new playback rate * @param format the format of the seek values * @param flags the optional seek flags * @param startType the type and flags for the new start position * @param start the value of the new start position * @param stopType the type and flags for the new stop position * @param stop the value of the new stop position * @return true if seek is successful */ public boolean seek(double rate, Format format, int flags, SeekType startType, long start, SeekType stopType, long stop) { return gst.gst_element_seek(this, rate, format, flags, startType, start, stopType, stop); } /** * Gets the current position in the media stream in units of time. * * @return the ClockTime representing the current position. */ public ClockTime queryPosition() { return ClockTime.valueOf(queryPosition(Format.TIME), TimeUnit.NANOSECONDS); } /** * Gets the current position in the media stream. * * @param unit the {@code TimeUnit} to return the position in terms of. * @return a time value representing the current position in units of unit. */ public long queryPosition(TimeUnit unit) { return unit.convert(queryPosition(Format.TIME), TimeUnit.NANOSECONDS); } /** * Gets the current position in terms of the specified {@link Format}. * * @param format The {@link Format} to return the position in. * @return The current position or -1 if the query failed. */ public long queryPosition(Format format) { Format[] fmt = { format }; long[] pos = { 0 }; return gst.gst_element_query_position(this, fmt, pos) ? pos[0] : -1L; } /** * Gets the time duration of the current media stream. * * @return The total duration of the current media stream. */ public ClockTime queryDuration() { return ClockTime.valueOf(queryDuration(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS); } /** * Gets the time duration of the current media stream. * * @param unit the {@code TimeUnit} to return the position in. * @return The total duration of the current media stream. */ public long queryDuration(TimeUnit unit) { Format[] fmt = { Format.TIME }; long[] duration = { 0 }; gst.gst_element_query_duration(this, fmt, duration); return unit.convert(duration[0], TimeUnit.NANOSECONDS); } /** * Gets the duration of the current media stream in terms of the specified {@link Format}. * * @param format the {@code Format} to return the duration in. * @return The total duration of the current media stream. */ public long queryDuration(Format format) { Format[] fmt = { format }; long[] duration = { 0 }; gst.gst_element_query_duration(this, fmt, duration); return duration[0]; } /** * Gets the {@link Segment} for the current media stream in terms of the specified {@link Format}. * * @return The information regarding the current {@code Segment}. */ public Segment querySegment() { return querySegment(Format.TIME); } /** * Gets the {@link Segment} for the current media stream in terms of the specified {@link Format}. * * @param format the {@code Format} to return the segment in. * @return The information regarding the current {@code Segment}. */ public Segment querySegment(Format format) { Query qry = GstQueryAPI.GSTQUERY_API.gst_query_new_segment(format); gst.gst_element_query(this, qry); double[] rate = { 0.0D }; Format[] fmt = { Format.UNDEFINED }; long[] start_value = { 0 }; long[] stop_value = { 0 }; GstQueryAPI.GSTQUERY_API.gst_query_parse_segment(qry, rate, fmt, start_value, stop_value); return new Segment(rate[0], fmt[0], start_value[0], stop_value[0]); } /** * Tests if the Pipeline is currently playing. * * @return true if the Pipeline is currently playing */ public boolean isPlaying() { return getState() == State.PLAYING; } /** * Tells the Pipeline to start playing the media stream. */ public void play() { setState(State.PLAYING); } /** * Tells the Pipeline to pause playing the media stream. */ public void pause() { setState(State.PAUSED); } /** * Tells the Pipeline to pause playing the media stream. */ public void stop() { setState(State.NULL); } }