Commit 2b1ce5f2 authored by Wim Taymans's avatar Wim Taymans

docs/design/: Some more docs in the works.

Original commit message from CVS:
* docs/design/part-dynamic.txt:
* docs/design/part-events.txt:
* docs/design/part-seeking.txt:
Some more docs in the works.

* gst/base/gstbasetransform.c: (gst_base_transform_transform_caps),
(gst_base_transform_getcaps), (gst_base_transform_configure_caps),
(gst_base_transform_setcaps), (gst_base_transform_get_size),
(gst_base_transform_buffer_alloc), (gst_base_transform_event),
(gst_base_transform_handle_buffer),
(gst_base_transform_sink_activate_push),
(gst_base_transform_src_activate_pull),
(gst_base_transform_set_passthrough),
(gst_base_transform_is_passthrough):
Refcounting fixes.

* gst/gstbus.c: (gst_bus_source_dispatch), (gst_bus_poll):
Cleanups.

* gst/gstevent.c: (gst_event_finalize):
Set SRC to NULL.

* gst/gstutils.c: (gst_element_unlink),
(gst_pad_get_parent_element), (gst_pad_proxy_getcaps),
(gst_pad_proxy_setcaps):
* gst/gstutils.h:
Add _get_parent_element() to get a pads parent as an element.
parent 3d531c89
2005-07-18 Wim Taymans <wim@fluendo.com>
* docs/design/part-dynamic.txt:
* docs/design/part-events.txt:
* docs/design/part-seeking.txt:
Some more docs in the works.
* gst/base/gstbasetransform.c: (gst_base_transform_transform_caps),
(gst_base_transform_getcaps), (gst_base_transform_configure_caps),
(gst_base_transform_setcaps), (gst_base_transform_get_size),
(gst_base_transform_buffer_alloc), (gst_base_transform_event),
(gst_base_transform_handle_buffer),
(gst_base_transform_sink_activate_push),
(gst_base_transform_src_activate_pull),
(gst_base_transform_set_passthrough),
(gst_base_transform_is_passthrough):
Refcounting fixes.
* gst/gstbus.c: (gst_bus_source_dispatch), (gst_bus_poll):
Cleanups.
* gst/gstevent.c: (gst_event_finalize):
Set SRC to NULL.
* gst/gstutils.c: (gst_element_unlink),
(gst_pad_get_parent_element), (gst_pad_proxy_getcaps),
(gst_pad_proxy_setcaps):
* gst/gstutils.h:
Add _get_parent_element() to get a pads parent as an element.
2005-07-18 Wim Taymans <wim@fluendo.com>
* check/gst/gstbin.c: (GST_START_TEST):
......
Dynamic pipelines
-----------------
This document describes many use cases for dynamically constructing and
manipulating a running or paused pipeline and the features provided by
GStreamer.
......@@ -163,6 +163,9 @@ The general flow of executing the seek with FLUSH is as follows:
6) start stopped tasks and unlock the STREAM_LOCK, dataflow will continue
now from the new position.
More information about the different seek types can be found in
part-seeking.txt.
SIZE
----
......
Seeking
-------
Seeking in GStreamer means configuring the pipeline for playback of the
media between a certain start and stop time.
Different kinds of seeking exist:
- immeditate seeking with low latency (FLUSH seek)
- seeking without flush, playback will start from the new
position after all the queues are emptied with old data.
- segment seeking with and without FLUSH, this can be used to
implement seamless looping or NLE functionality.
Seeking can be performed in different formats such as time, frames
or samples.
Seeking can be performed to an absolute position or relative to the
current playback position.
For seeking to work reliably, all plugins in the pipeline need to follow
the well-defined rules in this document.
Non segment seeking will make the pipeline emit EOS when the configured
playback range has been played.
Segment seeking will not emit an EOS at the end of the range but will
post a SEGMENT_STOP message on the bus. This message is posted by the
earliest element in the pipeline, typically a demuxer. After receiving
the message, the application can reconnect the pipeline or issue other
seek events in the pipeline.
Generating seeking events
-------------------------
The different kinds of seeking methods and their internal workings are
described below.
FLUSH seeking
-------------
This is the most common way of performing a seek in a playback application.
The application issues a seek on the pipeline and the new media is immediatly
played after the seek calls returns.
seeking without FLUSH
---------------------
This seek type is typically performed after issuing segment seeks to finish
the playback of the pipeline.
segment seeking with FLUSH
--------------------------
This seek is typically performed when starting seamless looping.
segment seeking without FLUSH
-----------------------------
This seek is typically performed when continuing seamless looping.
......@@ -231,7 +231,7 @@ gst_base_transform_getcaps (GstPad * pad)
GstPad *otherpad;
GstCaps *caps;
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
......@@ -272,6 +272,8 @@ gst_base_transform_getcaps (GstPad * pad)
done:
GST_DEBUG ("returning %" GST_PTR_FORMAT, caps);
gst_object_unref (trans);
return caps;
}
......@@ -306,7 +308,7 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
GstCaps *othercaps = NULL;
gboolean ret = TRUE;
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
......@@ -408,6 +410,8 @@ done:
if (othercaps)
gst_caps_unref (othercaps);
gst_object_unref (trans);
return ret;
/* ERRORS */
......@@ -479,7 +483,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
gboolean ret = FALSE;
gboolean unlock;
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (bclass->event)
......@@ -505,6 +509,8 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
if (unlock)
GST_STREAM_UNLOCK (pad);
gst_object_unref (trans);
return ret;
}
......@@ -670,13 +676,14 @@ gst_base_transform_sink_activate_push (GstPad * pad, gboolean active)
GstBaseTransform *trans;
GstBaseTransformClass *bclass;
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (active) {
if (bclass->start)
result = bclass->start (trans);
}
gst_object_unref (trans);
return result;
}
......@@ -688,7 +695,7 @@ gst_base_transform_src_activate_pull (GstPad * pad, gboolean active)
GstBaseTransform *trans;
GstBaseTransformClass *bclass;
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
result = gst_pad_activate_pull (trans->sinkpad, active);
......@@ -697,6 +704,7 @@ gst_base_transform_src_activate_pull (GstPad * pad, gboolean active)
if (result && bclass->start)
result &= bclass->start (trans);
}
gst_object_unref (trans);
return result;
}
......
......@@ -420,28 +420,30 @@ gst_bus_source_dispatch (GSource * source, GSourceFunc callback,
GstBusSource *bsource = (GstBusSource *) source;
GstMessage *message;
gboolean needs_pop = TRUE;
GstBus *bus;
g_return_val_if_fail (bsource != NULL, FALSE);
g_return_val_if_fail (GST_IS_BUS (bsource->bus), FALSE);
bus = bsource->bus;
message = gst_bus_peek (bsource->bus);
g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
message = gst_bus_peek (bus);
GST_DEBUG ("have message %p", message);
g_return_val_if_fail (message != NULL, TRUE);
if (!handler) {
g_warning ("GstBus watch dispatched without callback\n"
"You must call g_source_connect().");
return FALSE;
}
if (!handler)
goto no_handler;
GST_DEBUG ("calling dispatch with %p", message);
needs_pop = handler (bsource->bus, message, user_data);
needs_pop = handler (bus, message, user_data);
GST_DEBUG ("handler returns %d", needs_pop);
if (needs_pop) {
message = gst_bus_pop (bsource->bus);
message = gst_bus_pop (bus);
if (message) {
gst_message_unref (message);
} else {
......@@ -452,8 +454,14 @@ gst_bus_source_dispatch (GSource * source, GSourceFunc callback,
GST_DEBUG ("handler requested pop but no message on the bus");
}
}
return TRUE;
no_handler:
{
g_warning ("GstBus watch dispatched without callback\n"
"You must call g_source_connect().");
return FALSE;
}
}
static void
......@@ -596,6 +604,8 @@ poll_timeout (GstBusPollData * poll_data)
* specify a maximum time to poll with the @timeout parameter. If @timeout is
* negative, this function will block indefinitely.
*
* This function will enter the default mainloop while polling.
*
* Returns: The type of the message that was received, or GST_MESSAGE_UNKNOWN if
* the poll timed out. The message will remain in the bus queue; you will need
* to gst_bus_pop() it off before entering gst_bus_poll() again.
......@@ -603,28 +613,29 @@ poll_timeout (GstBusPollData * poll_data)
GstMessageType
gst_bus_poll (GstBus * bus, GstMessageType events, GstClockTimeDiff timeout)
{
GstBusPollData *poll_data;
GstBusPollData poll_data;
GstMessageType ret;
guint id;
poll_data = g_new0 (GstBusPollData, 1);
if (timeout >= 0)
poll_data->timeout_id = g_timeout_add (timeout / GST_MSECOND,
(GSourceFunc) poll_timeout, poll_data);
poll_data->loop = g_main_loop_new (NULL, FALSE);
poll_data->events = events;
poll_data->revent = GST_MESSAGE_UNKNOWN;
id = gst_bus_add_watch (bus, (GstBusHandler) poll_handler, poll_data);
g_main_loop_run (poll_data->loop);
poll_data.timeout_id = g_timeout_add (timeout / GST_MSECOND,
(GSourceFunc) poll_timeout, &poll_data);
else
poll_data.timeout_id = 0;
poll_data.loop = g_main_loop_new (NULL, FALSE);
poll_data.events = events;
poll_data.revent = GST_MESSAGE_UNKNOWN;
id = gst_bus_add_watch (bus, (GstBusHandler) poll_handler, &poll_data);
g_main_loop_run (poll_data.loop);
g_source_remove (id);
ret = poll_data->revent;
ret = poll_data.revent;
if (poll_data->timeout_id)
g_source_remove (poll_data->timeout_id);
g_main_loop_unref (poll_data->loop);
g_free (poll_data);
if (poll_data.timeout_id)
g_source_remove (poll_data.timeout_id);
g_main_loop_unref (poll_data.loop);
return ret;
}
......@@ -99,6 +99,7 @@ gst_event_finalize (GstEvent * event)
if (GST_EVENT_SRC (event)) {
gst_object_unref (GST_EVENT_SRC (event));
GST_EVENT_SRC (event) = NULL;
}
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_TAG:
......
......@@ -1443,7 +1443,9 @@ gst_element_unlink (GstElement * src, GstElement * dest)
/* see if the pad is connected and is really a pad
* of dest */
if (peerpad) {
GstElement *peerelem = gst_pad_get_parent (peerpad);
GstElement *peerelem;
peerelem = gst_pad_get_parent_element (peerpad);
if (peerelem == dest) {
gst_pad_unlink (pad, peerpad);
......@@ -1641,6 +1643,34 @@ done:
return result;
}
/**
* gst_pad_get_parent_element:
* @pad: a pad
*
* Gets the parent of @pad, cast to a #GstElement. If a @pad has no parent or
* its parent is not an element, return NULL.
*
* Returns: The parent of the pad. The caller has a reference on the parent, so
* unref when you're finished with it.
*
* MT safe.
*/
GstElement *
gst_pad_get_parent_element (GstPad * pad)
{
GstObject *p;
g_return_val_if_fail (GST_IS_PAD (pad), NULL);
p = gst_object_get_parent (GST_OBJECT_CAST (pad));
if (p && !GST_IS_ELEMENT (p)) {
gst_object_unref (p);
p = NULL;
}
return GST_ELEMENT_CAST (p);
}
/**
* gst_object_default_error:
* @object: a #GObject that signalled the error.
......@@ -1955,7 +1985,7 @@ gst_pad_proxy_getcaps (GstPad * pad)
GST_DEBUG ("proxying getcaps for %s:%s", GST_DEBUG_PAD_NAME (pad));
element = gst_pad_get_parent (pad);
element = gst_pad_get_parent_element (pad);
if (element == NULL)
return NULL;
......@@ -2027,7 +2057,7 @@ gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps)
GST_DEBUG ("proxying pad link for %s:%s", GST_DEBUG_PAD_NAME (pad));
element = gst_pad_get_parent (pad);
element = gst_pad_get_parent_element (pad);
iter = gst_element_iterate_pads (element);
......
......@@ -278,6 +278,8 @@ GstCaps* gst_pad_get_fixed_caps_func (GstPad *pad);
GstCaps* gst_pad_proxy_getcaps (GstPad * pad);
gboolean gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps);
GstElement* gst_pad_get_parent_element (GstPad *pad);
/* util query functions */
gboolean gst_pad_query_position (GstPad *pad, GstFormat *format,
gint64 *cur, gint64 *end);
......
......@@ -231,7 +231,7 @@ gst_base_transform_getcaps (GstPad * pad)
GstPad *otherpad;
GstCaps *caps;
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
......@@ -272,6 +272,8 @@ gst_base_transform_getcaps (GstPad * pad)
done:
GST_DEBUG ("returning %" GST_PTR_FORMAT, caps);
gst_object_unref (trans);
return caps;
}
......@@ -306,7 +308,7 @@ gst_base_transform_setcaps (GstPad * pad, GstCaps * caps)
GstCaps *othercaps = NULL;
gboolean ret = TRUE;
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
klass = GST_BASE_TRANSFORM_GET_CLASS (trans);
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
......@@ -408,6 +410,8 @@ done:
if (othercaps)
gst_caps_unref (othercaps);
gst_object_unref (trans);
return ret;
/* ERRORS */
......@@ -479,7 +483,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
gboolean ret = FALSE;
gboolean unlock;
trans = GST_BASE_TRANSFORM (GST_PAD_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (bclass->event)
......@@ -505,6 +509,8 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
if (unlock)
GST_STREAM_UNLOCK (pad);
gst_object_unref (trans);
return ret;
}
......@@ -670,13 +676,14 @@ gst_base_transform_sink_activate_push (GstPad * pad, gboolean active)
GstBaseTransform *trans;
GstBaseTransformClass *bclass;
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
if (active) {
if (bclass->start)
result = bclass->start (trans);
}
gst_object_unref (trans);
return result;
}
......@@ -688,7 +695,7 @@ gst_base_transform_src_activate_pull (GstPad * pad, gboolean active)
GstBaseTransform *trans;
GstBaseTransformClass *bclass;
trans = GST_BASE_TRANSFORM (GST_OBJECT_PARENT (pad));
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
bclass = GST_BASE_TRANSFORM_GET_CLASS (trans);
result = gst_pad_activate_pull (trans->sinkpad, active);
......@@ -697,6 +704,7 @@ gst_base_transform_src_activate_pull (GstPad * pad, gboolean active)
if (result && bclass->start)
result &= bclass->start (trans);
}
gst_object_unref (trans);
return result;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment