mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 03:00:35 +00:00
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.
This commit is contained in:
parent
3d531c895e
commit
2b1ce5f29e
10 changed files with 206 additions and 37 deletions
30
ChangeLog
30
ChangeLog
|
@ -1,3 +1,33 @@
|
|||
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):
|
||||
|
|
6
docs/design/part-dynamic.txt
Normal file
6
docs/design/part-dynamic.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
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
|
||||
----
|
||||
|
|
70
docs/design/part-seeking.txt
Normal file
70
docs/design/part-seeking.txt
Normal file
|
@ -0,0 +1,70 @@
|
|||
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;
|
||||
}
|
||||
|
|
59
gst/gstbus.c
59
gst/gstbus.c
|
@ -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 (GST_IS_BUS (bsource->bus), FALSE);
|
||||
g_return_val_if_fail (bsource != NULL, FALSE);
|
||||
|
||||
message = gst_bus_peek (bsource->bus);
|
||||
bus = 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;
|
||||
poll_data.timeout_id = g_timeout_add (timeout / GST_MSECOND,
|
||||
(GSourceFunc) poll_timeout, &poll_data);
|
||||
else
|
||||
poll_data.timeout_id = 0;
|
||||
|
||||
id = gst_bus_add_watch (bus, (GstBusHandler) poll_handler, poll_data);
|
||||
g_main_loop_run (poll_data->loop);
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue