* #GstBaseSink infrastructure should be sufficient.
*
* #GstBaseSink provides support for exactly one sink pad, which should be
- * named "sink". A sink implementation (subclass of GstBaseSink) should
+ * named "sink". A sink implementation (subclass of #GstBaseSink) should
* install a pad template in its base_init function, like so:
* <programlisting>
* static void
* </programlisting>
*
* #GstBaseSink will handle the prerolling correctly. This means that it will
- * return GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first
+ * return #GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first
* buffer arrives in this element. The base class will call the
- * GstBaseSink::preroll vmethod with this preroll buffer and will then commit
+ * #GstBaseSink::preroll vmethod with this preroll buffer and will then commit
* the state change to the next asynchronously pending state.
*
* When the element is set to PLAYING, #GstBaseSink will synchronise on the
* clock using the times returned from ::get_times. If this function returns
* #GST_CLOCK_TIME_NONE for the start time, no synchronisation will be done.
* Synchronisation can be disabled entirely by setting the object "sync"
- * property to FALSE.
+ * property to %FALSE.
*
* After synchronisation the virtual method #GstBaseSink::render will be called.
* Subclasses should minimally implement this method.
* Since 0.10.3 subclasses that synchronise on the clock in the ::render method
* are supported as well. These classes typically receive a buffer in the render
* method and can then potentially block on the clock while rendering. A typical
- * example is an audiosink.
+ * example is an audiosink. Since 0.10.11 these subclasses can use
+ * gst_base_sink_wait_preroll() to perform the blocking wait.
*
* Upon receiving the EOS event in the PLAYING state, #GstBaseSink will wait
* for the clock to reach the time indicated by the stop time of the last
* EOS in PAUSED, preroll completes, the event is queued and an EOS message is
* posted when going to PLAYING.
*
- * #GstBaseSink will internally use the GST_EVENT_NEW_SEGMENT events to schedule
+ * #GstBaseSink will internally use the #GST_EVENT_NEWSEGMENT events to schedule
* synchronisation and clipping of buffers. Buffers that fall completely outside
* of the current segment are dropped. Buffers that fall partially in the
* segment are rendered (and prerolled). Subclasses should do any subbuffer
* clipping themselves when needed.
*
* #GstBaseSink will by default report the current playback position in
- * GST_FORMAT_TIME based on the current clock time and segment information.
+ * #GST_FORMAT_TIME based on the current clock time and segment information.
* If no clock has been set on the element, the query will be forwarded
* upstream.
*
* synchronisation. For each dropped buffer it will also send a QoS message
* upstream.
*
- * Last reviewed on 2006-03-31 (0.10.5)
+ * Last reviewed on 2006-09-27 (0.10.11)
*/
#ifdef HAVE_CONFIG_H
* <para>
* The source can be configured to operate in any #GstFormat with the
* gst_base_src_set_format() method. The currently set format determines
- * the format of the internal #GstSegment and any #GST_EVENT_NEW_SEGMENT
+ * the format of the internal #GstSegment and any #GST_EVENT_NEWSEGMENT
* events. The default format for #GstBaseSrc is #GST_FORMAT_BYTES.
* </para>
* <para>
* #GstBaseSrc always supports push mode scheduling. If the following
* conditions are met, it also supports pull mode scheduling:
* <itemizedlist>
- * <listitem><para>The format is set to GST_FORMAT_BYTES (default).</para>
+ * <listitem><para>The format is set to #GST_FORMAT_BYTES (default).</para>
* </listitem>
- * <listitem><para>#GstBaseSrc::is_seekable returns TRUE.</para>
+ * <listitem><para>#GstBaseSrc::is_seekable returns %TRUE.</para>
* </listitem>
* </itemizedlist>
* </para>
* <para>
* Since 0.10.9, any #GstBaseSrc can enable pull based scheduling at any
- * time by overriding #GstBaseSrc::check_get_range so that it returns TRUE.
+ * time by overriding #GstBaseSrc::check_get_range so that it returns %TRUE.
* </para>
* <para>
* If all the conditions are met for operating in pull mode, #GstBaseSrc is
* automatically seekable in push mode as well. The following conditions must
* be met to make the element seekable in push mode when the format is not
- * GST_FORMAT_BYTES:
+ * #GST_FORMAT_BYTES:
* <itemizedlist>
* <listitem><para>
- * #GstBaseSrc::is_seekable returns TRUE.
+ * #GstBaseSrc::is_seekable returns %TRUE.
* </para></listitem>
* <listitem><para>
* #GstBaseSrc::query can convert all supported seek formats to the
* internal format as set with gst_base_src_set_format().
* </para></listitem>
* <listitem><para>
- * #GstBaseSrc::do_seek is implemented, performs the seek and returns TRUE.
+ * #GstBaseSrc::do_seek is implemented, performs the seek and returns %TRUE.
* </para></listitem>
* </itemizedlist>
* </para>
* A live source does not produce data in the PAUSED state. This means that the
* #GstBaseSrc::create method will not be called in PAUSED but only in PLAYING.
* To signal the pipeline that the element will not produce data, the return
- * value from the READY to PAUSED state will be GST_STATE_CHANGE_NO_PREROLL.
+ * value from the READY to PAUSED state will be #GST_STATE_CHANGE_NO_PREROLL.
* </para>
* <para>
* A typical live source will timestamp the buffers it creates with the
* distributed and running.
* </para>
* <para>
+ * Live sources that synchronize and block on the clock (and audio source, for
+ * example) can since 0.10.12 use gst_base_src_wait_playing() when the ::create
+ * function was interrupted by a state change to PAUSED.
+ * </para>
+ * <para>
* The #GstBaseSrc::get_times method can be used to implement pseudo-live
* sources. The base source will wait for the specified stream time returned in
* #GstBaseSrc::get_times before pushing out the buffer.
* a live source.
* </para>
* <para>
- * There is only support in GstBaseSrc for exactly one source pad, which
- * should be named "src". A source implementation (subclass of GstBaseSrc)
+ * There is only support in #GstBaseSrc for exactly one source pad, which
+ * should be named "src". A source implementation (subclass of #GstBaseSrc)
* should install a pad template in its base_init function, like so:
* </para>
* <para>
* <programlisting>
* ...
* // stop recording
- * gst_element_set_state (audio_source, GST_STATE_NULL);
- * gst_element_set_locked_state (audio_source, TRUE);
+ * gst_element_set_state (audio_source, #GST_STATE_NULL);
+ * gst_element_set_locked_state (audio_source, %TRUE);
* ...
* </programlisting>
* Now the application should wait for an EOS message
* <programlisting>
* ...
* // everything done - shut down pipeline
- * gst_element_set_state (pipeline, GST_STATE_NULL);
- * gst_element_set_locked_state (audio_source, FALSE);
+ * gst_element_set_state (pipeline, #GST_STATE_NULL);
+ * gst_element_set_locked_state (audio_source, %FALSE);
* ...
* </programlisting>
* </para>
* thread might be blocked in PREROLL.
* </para>
* <para>
- * Last reviewed on 2006-07-06 (0.10.9)
+ * Last reviewed on 2006-09-27 (0.10.11)
* </para>
* </refsect2>
*/
}
/**
+ * gst_base_src_wait_playing:
+ * @src: the src
+ *
+ * If the #GstBaseSrcClass::create method performs its own synchronisation against
+ * the clock it must unblock when going from PLAYING to the PAUSED state and call
+ * this method before continuing to produce the remaining data.
+ *
+ * This function will block until a state change to PLAYING happens (in which
+ * case this function returns #GST_FLOW_OK) or the processing must be stopped due
+ * to a state change to READY or a FLUSH event (in which case this function
+ * returns #GST_FLOW_WRONG_STATE).
+ *
+ * Since: 0.10.12
+ *
+ * Returns: #GST_FLOW_OK if @src is PLAYING and processing can
+ * continue. Any other return value should be returned from the create vmethod.
+ */
+GstFlowReturn
+gst_base_src_wait_playing (GstBaseSrc * src)
+{
+ /* block until the state changes, or we get a flush, or something */
+ GST_LIVE_LOCK (src);
+ if (src->is_live) {
+ while (G_UNLIKELY (!src->live_running)) {
+ GST_DEBUG ("live source signal waiting");
+ GST_LIVE_SIGNAL (src);
+ GST_DEBUG ("live source waiting for running state");
+ GST_LIVE_WAIT (src);
+ GST_DEBUG ("live source unlocked");
+ }
+ /* FIXME, use another variable to signal stopping so that we don't
+ * have to grab another lock. */
+ GST_OBJECT_LOCK (src->srcpad);
+ if (G_UNLIKELY (GST_PAD_IS_FLUSHING (src->srcpad)))
+ goto flushing;
+ GST_OBJECT_UNLOCK (src->srcpad);
+ }
+ GST_LIVE_UNLOCK (src);
+
+ return GST_FLOW_OK;
+
+ /* ERRORS */
+flushing:
+ {
+ GST_DEBUG_OBJECT (src, "pad is flushing");
+ GST_OBJECT_UNLOCK (src->srcpad);
+ GST_LIVE_UNLOCK (src);
+ return GST_FLOW_WRONG_STATE;
+ }
+}
+
+/**
* gst_base_src_set_live:
* @src: base source instance
* @live: new live-mode
bclass = GST_BASE_SRC_GET_CLASS (src);
- GST_LIVE_LOCK (src);
- if (src->is_live) {
- while (G_UNLIKELY (!src->live_running)) {
- GST_DEBUG ("live source signal waiting");
- GST_LIVE_SIGNAL (src);
- GST_DEBUG ("live source waiting for running state");
- GST_LIVE_WAIT (src);
- GST_DEBUG ("live source unlocked");
- }
- /* FIXME, use another variable to signal stopping so that we don't
- * have to grab another lock. */
- GST_OBJECT_LOCK (src->srcpad);
- if (G_UNLIKELY (GST_PAD_IS_FLUSHING (src->srcpad)))
- goto flushing;
- GST_OBJECT_UNLOCK (src->srcpad);
- }
- GST_LIVE_UNLOCK (src);
+ ret = gst_base_src_wait_playing (src);
+ if (ret != GST_FLOW_OK)
+ goto stopped;
if (G_UNLIKELY (!GST_OBJECT_FLAG_IS_SET (src, GST_BASE_SRC_STARTED)))
goto not_started;
return ret;
/* ERROR */
-flushing:
+stopped:
{
- GST_DEBUG_OBJECT (src, "pad is flushing");
- GST_OBJECT_UNLOCK (src->srcpad);
- GST_LIVE_UNLOCK (src);
- return GST_FLOW_WRONG_STATE;
+ GST_DEBUG_OBJECT (src, "wait_playing returned %d", ret);
+ return ret;
}
not_started:
{