gst/gstbin.c: Add default event/set_manager handlers. The set_manager handler takes care that the manager is distribu...

Original commit message from CVS:
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_manager),
(gst_bin_send_event):
Add default event/set_manager handlers. The set_manager handler
takes care that the manager is distributed over kids that were
already in the bin before the manager was set. The event handler
is a utility virtual function that sends the event over all sinks,
so that gst_element_send_event (bin, event); has the expected
behaviour.
* gst/gstpad.c: (gst_pad_event_default):
Re-install default event handling for discontinuities, so that
seeking works without requiring hacks in applications or extra
code in sinks.
* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_send_event):
Half hack, half utility: set a pipeline to PAUSED for seek events,
since that is the only way we can guarantee a/v sync. Means that
you can do gst_element_seek (pipeline, method, pos); on a pipeline
and it "just works".
This commit is contained in:
Ronald S. Bultje 2005-03-25 09:57:42 +00:00
parent f96e2fabad
commit 8eb4bb6a51
4 changed files with 121 additions and 4 deletions

View file

@ -1,3 +1,24 @@
2005-03-25 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_manager),
(gst_bin_send_event):
Add default event/set_manager handlers. The set_manager handler
takes care that the manager is distributed over kids that were
already in the bin before the manager was set. The event handler
is a utility virtual function that sends the event over all sinks,
so that gst_element_send_event (bin, event); has the expected
behaviour.
* gst/gstpad.c: (gst_pad_event_default):
Re-install default event handling for discontinuities, so that
seeking works without requiring hacks in applications or extra
code in sinks.
* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_send_event):
Half hack, half utility: set a pipeline to PAUSED for seek events,
since that is the only way we can guarantee a/v sync. Means that
you can do gst_element_seek (pipeline, method, pos); on a pipeline
and it "just works".
2005-03-25 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* gst/gstpipeline.c: (gst_pipeline_use_clock):

View file

@ -61,6 +61,9 @@ static GstElementStateReturn gst_bin_get_state (GstElement * element,
static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
static void gst_bin_set_manager (GstElement * element, GstPipeline * manager);
static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
#ifndef GST_DISABLE_INDEX
static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
#endif
@ -166,6 +169,8 @@ gst_bin_class_init (GstBinClass * klass)
GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
#endif
gstelement_class->set_manager = GST_DEBUG_FUNCPTR (gst_bin_set_manager);
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state);
#ifndef GST_DISABLE_INDEX
@ -787,6 +792,60 @@ gst_bin_dispose (GObject * object)
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_bin_set_manager (GstElement * element, GstPipeline * manager)
{
GstBin *bin = GST_BIN (element);
GList *kids;
GstElement *kid;
GST_ELEMENT_CLASS (parent_class)->set_manager (element, manager);
GST_LOCK (element);
for (kids = bin->children; kids != NULL; kids = kids->next) {
kid = GST_ELEMENT (kids->data);
gst_element_set_manager (kid, manager);
}
GST_UNLOCK (element);
}
/*
* This function is a utility event handler for seek events.
* It will change pipeline state to PAUSED, iterate event
* over all available sinks, distribute new basetime to the
* pipeline after preroll is done and then re-set to PLAYING.
* Applications are free to override this behaviour and
* implement their own seek handler, but this will work for
* pretty much all cases in practice.
*/
static gboolean
gst_bin_send_event (GstElement * element, GstEvent * event)
{
GstBin *bin = GST_BIN (element);
GstIterator *iter;
GstElement *sink;
gpointer data;
gboolean res = TRUE;
iter = gst_bin_iterate_sinks (bin);
GST_DEBUG_OBJECT (bin, "Sending event to sink children");
/* iterate over all sinks; preroll will take care of sync,
* discont event handling will take care of proper clock
* adjustment. Sweet. */
while (gst_iterator_next (iter, &data) == GST_ITERATOR_OK) {
gst_event_ref (event);
sink = GST_ELEMENT (data);
res &= gst_element_send_event (sink, event);
gst_object_unref (GST_OBJECT (sink));
}
gst_iterator_free (iter);
gst_event_unref (event);
return res;
}
static gint
compare_name (GstElement * element, const gchar * name)
{

View file

@ -26,6 +26,7 @@
#include "gstmarshal.h"
#include "gstutils.h"
#include "gstelement.h"
#include "gstpipeline.h"
#include "gstbin.h"
#include "gstscheduler.h"
#include "gstevent.h"
@ -3381,6 +3382,7 @@ done:
*
* Returns: TRUE if the event was sent succesfully.
*/
gboolean
gst_pad_event_default (GstPad * pad, GstEvent * event)
{
@ -3388,8 +3390,17 @@ gst_pad_event_default (GstPad * pad, GstEvent * event)
g_return_val_if_fail (event != NULL, FALSE);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
{
case GST_EVENT_DISCONTINUOUS:{
GstElement *element = gst_pad_get_parent (pad);
guint64 time;
if (element && element->clock && GST_ELEMENT_MANAGER (element) &&
gst_event_discont_get_value (event, GST_FORMAT_TIME, &time)) {
GST_PIPELINE (GST_ELEMENT_MANAGER (element))->stream_time = time;
}
break;
}
case GST_EVENT_EOS:{
GstRealPad *rpad = GST_PAD_REALIZE (pad);
if (GST_RPAD_TASK (rpad)) {
@ -3397,10 +3408,11 @@ gst_pad_event_default (GstPad * pad, GstEvent * event)
gst_task_pause (GST_RPAD_TASK (rpad));
}
}
return gst_pad_event_default_dispatch (pad, event);
default:
return gst_pad_event_default_dispatch (pad, event);
break;
}
return gst_pad_event_default_dispatch (pad, event);
}
/**

View file

@ -61,6 +61,8 @@ static void gst_pipeline_set_property (GObject * object, guint prop_id,
static void gst_pipeline_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean gst_pipeline_send_event (GstElement * element,
GstEvent * event);
static GstBusSyncReply pipeline_bus_handler (GstBus * bus, GstMessage * message,
GstPipeline * pipeline);
@ -128,6 +130,7 @@ gst_pipeline_class_init (gpointer g_class, gpointer class_data)
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_pipeline_send_event);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_pipeline_get_clock_func);
@ -274,6 +277,28 @@ is_eos (GstPipeline * pipeline)
return result;
}
static gboolean
gst_pipeline_send_event (GstElement * element, GstEvent * event)
{
gboolean was_playing;
gboolean res;
GST_STATE_LOCK (element);
/* hmm... questionable */
was_playing = (GST_STATE (element) == GST_STATE_PLAYING);
GST_STATE_UNLOCK (element);
if (was_playing && GST_EVENT_TYPE (event) == GST_EVENT_SEEK)
gst_element_set_state (element, GST_STATE_PAUSED);
res = GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
if (was_playing && GST_EVENT_TYPE (event) == GST_EVENT_SEEK)
gst_element_set_state (element, GST_STATE_PLAYING);
return res;
}
/* FIXME, make me threadsafe */
static GstBusSyncReply
pipeline_bus_handler (GstBus * bus, GstMessage * message,