mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
- Elements can now send events to their parent.
Original commit message from CVS: - Elements can now send events to their parent. - remove the g_signals from the core for parent<->child communication - the application can easily get element info by listening for an event signal from the toplevel bin. - added gst_element_info()/_error(). - fakesrc and fakesink use the info event instead of g_print. - GST_TYPE_* causes segfaults with elect fence, rever to G_TYPE_POINTER until we know what's wrong. - various leaks fixed wrt element destroy. - The object that created the event is now stored as GST_EVENT_SRC
This commit is contained in:
parent
19bb74b352
commit
56d3cdf64a
14 changed files with 317 additions and 112 deletions
|
@ -226,9 +226,10 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
|
|||
}
|
||||
*/
|
||||
|
||||
if (!fakesink->silent)
|
||||
g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) %p\n",
|
||||
if (!fakesink->silent) {
|
||||
gst_element_info (GST_ELEMENT (fakesink), "chain ******* (%s:%s)< (%d bytes, %lld) %p",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
|
||||
}
|
||||
|
||||
g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
|
||||
|
||||
|
|
|
@ -300,6 +300,8 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
|||
srcpad = gst_pad_new_from_template (templ, name);
|
||||
gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
|
||||
|
||||
g_free (name);
|
||||
|
||||
return srcpad;
|
||||
}
|
||||
|
||||
|
@ -312,7 +314,6 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
|||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
g_print("fakesrc: have seek event\n");
|
||||
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
||||
if (!GST_EVENT_SEEK_FLUSH (event)) {
|
||||
gst_event_free (event);
|
||||
|
@ -320,11 +321,9 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
|||
}
|
||||
/* else we do a flush too */
|
||||
case GST_EVENT_FLUSH:
|
||||
g_print("fakesrc: have flush event\n");
|
||||
src->need_flush = TRUE;
|
||||
break;
|
||||
default:
|
||||
g_print("fakesrc: have unhandled event\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -646,12 +645,10 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
if (src->need_flush) {
|
||||
src->need_flush = FALSE;
|
||||
g_print("fakesrc: sending FLUSH\n");
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
|
||||
}
|
||||
|
||||
if (src->rt_num_buffers == 0) {
|
||||
g_print("fakesrc: sending EOS\n");
|
||||
gst_element_set_state (GST_ELEMENT (src), GST_STATE_PAUSED);
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
@ -662,16 +659,17 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
if (src->eos) {
|
||||
GST_INFO (0, "fakesrc is setting eos on pad");
|
||||
g_print("fakesrc: sending EOS\n");
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
||||
buf = gst_fakesrc_create_buffer (src);
|
||||
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
|
||||
|
||||
if (!src->silent)
|
||||
g_print("fakesrc: get ******* (%s:%s)> (%d bytes, %llu) \n",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
if (!src->silent) {
|
||||
gst_element_info (GST_ELEMENT (src),
|
||||
"get ******* (%s:%s)> (%d bytes, %llu)",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
}
|
||||
|
||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "pre handoff emit\n");
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
|
@ -715,7 +713,6 @@ gst_fakesrc_loop(GstElement *element)
|
|||
}
|
||||
|
||||
if (src->eos) {
|
||||
GST_INFO (0, "fakesrc is setting eos on pad");
|
||||
gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
|
||||
return;
|
||||
}
|
||||
|
@ -723,9 +720,10 @@ gst_fakesrc_loop(GstElement *element)
|
|||
buf = gst_fakesrc_create_buffer (src);
|
||||
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
|
||||
|
||||
if (!src->silent)
|
||||
g_print("fakesrc: loop ******* (%s:%s) > (%d bytes, %llu) \n",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
if (!src->silent) {
|
||||
gst_element_info (element, "fakesrc: loop ******* (%s:%s) > (%d bytes, %llu)",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
}
|
||||
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
buf, pad);
|
||||
|
@ -768,9 +766,6 @@ gst_fakesrc_change_state (GstElement *element)
|
|||
break;
|
||||
}
|
||||
|
||||
if (GST_STATE_PENDING (element) == GST_STATE_READY) {
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
|
|
53
gst/gstbin.c
53
gst/gstbin.c
|
@ -23,6 +23,7 @@
|
|||
/* #define GST_DEBUG_ENABLED */
|
||||
#include "gst_private.h"
|
||||
|
||||
#include "gstevent.h"
|
||||
#include "gstbin.h"
|
||||
|
||||
#include "gstscheduler.h"
|
||||
|
@ -40,11 +41,14 @@ GType _gst_bin_type = 0;
|
|||
|
||||
static void gst_bin_dispose (GObject * object);
|
||||
|
||||
static GstElementStateReturn gst_bin_change_state (GstElement * element);
|
||||
static GstElementStateReturn gst_bin_change_state_norecurse (GstBin * bin);
|
||||
static gboolean gst_bin_change_state_type (GstBin * bin, GstElementState state, GType type);
|
||||
static void gst_bin_child_state_change (GstBin * bin, GstElementState old,
|
||||
GstElementState new, GstElement * element);
|
||||
static GstElementStateReturn gst_bin_change_state (GstElement *element);
|
||||
static GstElementStateReturn gst_bin_change_state_norecurse (GstBin *bin);
|
||||
static gboolean gst_bin_change_state_type (GstBin *bin,
|
||||
GstElementState state,
|
||||
GType type);
|
||||
static void gst_bin_child_state_change (GstBin *bin, GstElementState old,
|
||||
GstElementState new, GstElement *child);
|
||||
static void gst_bin_send_event (GstElement *element, GstEvent *event);
|
||||
|
||||
static gboolean gst_bin_iterate_func (GstBin * bin);
|
||||
|
||||
|
@ -110,7 +114,10 @@ gst_bin_class_init (GstBinClass * klass)
|
|||
gst_bin_signals[OBJECT_ADDED] =
|
||||
g_signal_new ("object_added", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GstBinClass, object_added), NULL, NULL,
|
||||
gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
||||
gst_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
|
||||
|
||||
klass->change_state_type = GST_DEBUG_FUNCPTR (gst_bin_change_state_type);
|
||||
klass->iterate = GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
|
||||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
|
@ -119,6 +126,7 @@ gst_bin_class_init (GstBinClass * klass)
|
|||
#endif
|
||||
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
|
||||
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
|
||||
|
||||
klass->change_state_type = GST_DEBUG_FUNCPTR (gst_bin_change_state_type);
|
||||
klass->iterate = GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
|
||||
|
@ -272,8 +280,6 @@ gst_bin_add (GstBin * bin, GstElement * element)
|
|||
|
||||
/* set the element's parent and add the element to the bin's list of children */
|
||||
gst_object_set_parent (GST_OBJECT (element), GST_OBJECT (bin));
|
||||
g_signal_connect_swapped (G_OBJECT (element), "state_change",
|
||||
G_CALLBACK (gst_bin_child_state_change), G_OBJECT (bin));
|
||||
|
||||
bin->children = g_list_append (bin->children, element);
|
||||
bin->numchildren++;
|
||||
|
@ -384,10 +390,33 @@ gst_bin_child_state_change (GstBin * bin, GstElementState old, GstElementState n
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GST_UNLOCK (bin);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_bin_send_event (GstElement *element, GstEvent *event)
|
||||
{
|
||||
GST_DEBUG (GST_CAT_EVENT, "event from %s in %s\n",
|
||||
gst_element_get_name (GST_ELEMENT (GST_EVENT_SRC (event))),
|
||||
gst_element_get_name (element));
|
||||
|
||||
if (GST_ELEMENT (GST_EVENT_SRC (event)) == element) {
|
||||
GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_STATE_CHANGE:
|
||||
gst_bin_child_state_change (GST_BIN (element), GST_EVENT_STATE_OLD (event),
|
||||
GST_EVENT_STATE_NEW (event), GST_ELEMENT (GST_EVENT_SRC (event)));
|
||||
gst_event_free (event);
|
||||
break;
|
||||
default:
|
||||
GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_bin_change_state (GstElement * element)
|
||||
{
|
||||
|
@ -432,8 +461,10 @@ gst_bin_change_state (GstElement * element)
|
|||
}
|
||||
}
|
||||
|
||||
GST_INFO_ELEMENT (GST_CAT_STATES, element, "done changing bin's state from %s to %s",
|
||||
gst_element_statename (old_state), gst_element_statename (pending));
|
||||
GST_INFO_ELEMENT (GST_CAT_STATES, element, "done changing bin's state from %s to %s, now in %s",
|
||||
gst_element_statename (old_state),
|
||||
gst_element_statename (pending),
|
||||
gst_element_statename (GST_STATE (element)));
|
||||
|
||||
if (have_async)
|
||||
ret = GST_STATE_ASYNC;
|
||||
|
|
166
gst/gstelement.c
166
gst/gstelement.c
|
@ -29,6 +29,7 @@
|
|||
#include "gstextratypes.h"
|
||||
#include "gstbin.h"
|
||||
#include "gstscheduler.h"
|
||||
#include "gstevent.h"
|
||||
#include "gstutils.h"
|
||||
|
||||
/* Element signals and args */
|
||||
|
@ -37,6 +38,7 @@ enum {
|
|||
NEW_PAD,
|
||||
PAD_REMOVED,
|
||||
ERROR,
|
||||
EVENT,
|
||||
EOS,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
@ -59,6 +61,7 @@ static void gst_element_get_property (GObject *object, guint prop_id, GValue *
|
|||
static void gst_element_dispose (GObject *object);
|
||||
|
||||
static GstElementStateReturn gst_element_change_state (GstElement *element);
|
||||
static void gst_element_send_event_func (GstElement *element, GstEvent *event);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
static xmlNodePtr gst_element_save_thyself (GstObject *object, xmlNodePtr parent);
|
||||
|
@ -102,27 +105,32 @@ gst_element_class_init (GstElementClass *klass)
|
|||
parent_class = g_type_class_ref(GST_TYPE_OBJECT);
|
||||
|
||||
gst_element_signals[STATE_CHANGE] =
|
||||
g_signal_new ("state_change", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("state_change", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass, state_change), NULL, NULL,
|
||||
gst_marshal_VOID__INT_INT, G_TYPE_NONE, 2,
|
||||
G_TYPE_INT, G_TYPE_INT);
|
||||
gst_element_signals[NEW_PAD] =
|
||||
g_signal_new ("new_pad", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("new_pad", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass, new_pad), NULL, NULL,
|
||||
gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
|
||||
GST_TYPE_PAD);
|
||||
gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
gst_element_signals[PAD_REMOVED] =
|
||||
g_signal_new ("pad_removed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("pad_removed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass, pad_removed), NULL, NULL,
|
||||
gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
|
||||
GST_TYPE_PAD);
|
||||
gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
gst_element_signals[ERROR] =
|
||||
g_signal_new ("error", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("error", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass, error), NULL, NULL,
|
||||
gst_marshal_VOID__STRING, G_TYPE_NONE,1,
|
||||
G_TYPE_STRING);
|
||||
G_TYPE_STRING);
|
||||
gst_element_signals[EVENT] =
|
||||
g_signal_new ("event", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass, event), NULL, NULL,
|
||||
gst_marshal_VOID__POINTER, G_TYPE_NONE,1,
|
||||
G_TYPE_POINTER);
|
||||
gst_element_signals[EOS] =
|
||||
g_signal_new ("eos", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstElementClass,eos), NULL, NULL,
|
||||
gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
|
||||
|
||||
|
@ -138,9 +146,10 @@ gst_element_class_init (GstElementClass *klass)
|
|||
#endif
|
||||
|
||||
klass->change_state = GST_DEBUG_FUNCPTR (gst_element_change_state);
|
||||
klass->elementfactory = NULL;
|
||||
klass->padtemplates = NULL;
|
||||
klass->numpadtemplates = 0;
|
||||
klass->send_event = GST_DEBUG_FUNCPTR (gst_element_send_event_func);
|
||||
klass->elementfactory = NULL;
|
||||
klass->padtemplates = NULL;
|
||||
klass->numpadtemplates = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -158,7 +167,7 @@ static void
|
|||
gst_element_init (GstElement *element)
|
||||
{
|
||||
element->current_state = GST_STATE_NULL;
|
||||
element->pending_state = -1;
|
||||
element->pending_state = GST_STATE_VOID_PENDING;
|
||||
element->numpads = 0;
|
||||
element->numsrcpads = 0;
|
||||
element->numsinkpads = 0;
|
||||
|
@ -166,6 +175,8 @@ gst_element_init (GstElement *element)
|
|||
element->loopfunc = NULL;
|
||||
element->threadstate = NULL;
|
||||
element->sched = NULL;
|
||||
element->state_mutex = g_mutex_new ();
|
||||
element->state_cond = g_cond_new ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -760,6 +771,21 @@ gst_element_disconnect (GstElement *src, const gchar *srcpadname,
|
|||
gst_pad_disconnect(srcpad,destpad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_element_message (GstElement *element, const gchar *type, const gchar *info, va_list var_args)
|
||||
{
|
||||
GstEvent *event;
|
||||
GstProps *props;
|
||||
gchar *string;
|
||||
|
||||
string = g_strdup_vprintf (info, var_args);
|
||||
|
||||
event = gst_event_new_info (type, GST_PROPS_STRING (string), NULL);
|
||||
gst_element_send_event (element, event);
|
||||
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_error:
|
||||
* @element: Element with the error
|
||||
|
@ -769,15 +795,75 @@ gst_element_disconnect (GstElement *src, const gchar *srcpadname,
|
|||
* condition. It results in the "error" signal.
|
||||
*/
|
||||
void
|
||||
gst_element_error (GstElement *element, const gchar *error)
|
||||
gst_element_error (GstElement *element, const gchar *error, ...)
|
||||
{
|
||||
g_error("GstElement: error in element '%s': %s\n", GST_ELEMENT_NAME(element), error);
|
||||
|
||||
/* FIXME: this is not finished!!! */
|
||||
|
||||
g_signal_emit (G_OBJECT (element), gst_element_signals[ERROR], 0, error);
|
||||
va_list var_args;
|
||||
|
||||
va_start (var_args, error);
|
||||
gst_element_message (element, "error", error, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_info:
|
||||
* @element: Element with the info
|
||||
* @info: String describing the info
|
||||
*
|
||||
* This function is used internally by elements to signal an info
|
||||
* condition. It results in the "info" signal.
|
||||
*/
|
||||
void
|
||||
gst_element_info (GstElement *element, const gchar *info, ...)
|
||||
{
|
||||
va_list var_args;
|
||||
|
||||
va_start (var_args, info);
|
||||
gst_element_message (element, "info", info, var_args);
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_element_send_event_func (GstElement *element, GstEvent *event)
|
||||
{
|
||||
if (GST_OBJECT_PARENT (element)) {
|
||||
gst_element_send_event (GST_ELEMENT (GST_OBJECT_PARENT (element)), event);
|
||||
}
|
||||
else {
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_STATE_CHANGE:
|
||||
g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE], 0,
|
||||
GST_EVENT_STATE_OLD (event), GST_EVENT_STATE_NEW (event));
|
||||
default:
|
||||
g_signal_emit (G_OBJECT (element), gst_element_signals[EVENT], 0, event);
|
||||
}
|
||||
gst_event_free (event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_send_event:
|
||||
* @element: Element generating the event
|
||||
* @event: the event to send
|
||||
*
|
||||
* This function is used intenally by elements to send an event to
|
||||
* the app. It will result in an "event" signal.
|
||||
*/
|
||||
void
|
||||
gst_element_send_event (GstElement *element, GstEvent *event)
|
||||
{
|
||||
GstElementClass *oclass = (GstElementClass *) G_OBJECT_GET_CLASS (element);
|
||||
|
||||
g_return_if_fail (GST_IS_ELEMENT (element));
|
||||
g_return_if_fail (event);
|
||||
|
||||
if (GST_EVENT_SRC (event) == NULL)
|
||||
GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (element));
|
||||
|
||||
if (oclass->send_event)
|
||||
(oclass->send_event) (element, event);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_get_state:
|
||||
|
@ -795,13 +881,6 @@ gst_element_get_state (GstElement *element)
|
|||
return GST_STATE (element);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_element_wait_done (GstElement *element, GstElementState old, GstElementState new, GCond *cond)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (element), gst_element_wait_done, cond);
|
||||
g_cond_signal (cond);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_wait_state_change:
|
||||
* @element: element wait for
|
||||
|
@ -811,17 +890,9 @@ gst_element_wait_done (GstElement *element, GstElementState old, GstElementState
|
|||
void
|
||||
gst_element_wait_state_change (GstElement *element)
|
||||
{
|
||||
GCond *cond = g_cond_new ();
|
||||
GMutex *mutex = g_mutex_new ();
|
||||
|
||||
g_mutex_lock (mutex);
|
||||
g_signal_connect (G_OBJECT (element), "state_change",
|
||||
G_CALLBACK (gst_element_wait_done), cond);
|
||||
g_cond_wait (cond, mutex);
|
||||
g_mutex_unlock (mutex);
|
||||
|
||||
g_mutex_free (mutex);
|
||||
g_cond_free (cond);
|
||||
g_mutex_lock (element->state_mutex);
|
||||
g_cond_wait (element->state_cond, element->state_mutex);
|
||||
g_mutex_unlock (element->state_mutex);
|
||||
}
|
||||
/**
|
||||
* gst_element_set_state:
|
||||
|
@ -935,14 +1006,15 @@ gst_element_change_state (GstElement *element)
|
|||
GST_STATE (element) = GST_STATE_PENDING (element);
|
||||
GST_STATE_PENDING (element) = GST_STATE_VOID_PENDING;
|
||||
|
||||
/* note: queues' state_change is a special case because it needs to lock
|
||||
* for synchronization (from another thread). since this signal may block
|
||||
* or (worse) make another state change, the queue needs to unlock before
|
||||
* calling. thus, gstqueue.c::gst_queue_state_change() blocks, unblocks,
|
||||
* unlocks, then emits this.
|
||||
*/
|
||||
g_signal_emit (G_OBJECT (element), gst_element_signals[STATE_CHANGE], 0,
|
||||
old_state, GST_STATE (element));
|
||||
g_mutex_lock (element->state_mutex);
|
||||
g_cond_signal (element->state_cond);
|
||||
g_mutex_unlock (element->state_mutex);
|
||||
|
||||
{
|
||||
GstEvent *event = gst_event_new_state_change (old_state, GST_STATE (element));
|
||||
|
||||
gst_element_send_event (element, event);
|
||||
}
|
||||
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
@ -995,6 +1067,8 @@ gst_element_dispose (GObject *object)
|
|||
element->numsrcpads = 0;
|
||||
element->numsinkpads = 0;
|
||||
element->numpads = 0;
|
||||
g_mutex_free (element->state_mutex);
|
||||
g_cond_free (element->state_cond);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <gst/gstconfig.h>
|
||||
|
||||
#include <gst/gsttypes.h>
|
||||
#include <gst/gstobject.h>
|
||||
#include <gst/gstpad.h>
|
||||
#include <gst/cothreads.h>
|
||||
|
@ -37,20 +38,23 @@ extern "C" {
|
|||
|
||||
#define GST_NUM_STATES 4
|
||||
|
||||
typedef enum {
|
||||
GST_STATE_VOID_PENDING = 0,
|
||||
GST_STATE_NULL = (1 << 0),
|
||||
GST_STATE_READY = (1 << 1),
|
||||
GST_STATE_PAUSED = (1 << 2),
|
||||
GST_STATE_PLAYING = (1 << 3),
|
||||
} GstElementState;
|
||||
//typedef enum _GstElementState GstElementState;
|
||||
//typedef enum _GstElementStateReturn GstElementStateReturn;
|
||||
|
||||
typedef enum {
|
||||
GST_STATE_FAILURE = 0,
|
||||
GST_STATE_SUCCESS = 1,
|
||||
GST_STATE_ASYNC = 2,
|
||||
} GstElementStateReturn;
|
||||
|
||||
enum _GstElementState {
|
||||
GST_STATE_VOID_PENDING = 0,
|
||||
GST_STATE_NULL = (1 << 0),
|
||||
GST_STATE_READY = (1 << 1),
|
||||
GST_STATE_PAUSED = (1 << 2),
|
||||
GST_STATE_PLAYING = (1 << 3),
|
||||
};
|
||||
|
||||
enum _GstElementStateReturn {
|
||||
GST_STATE_FAILURE = 0,
|
||||
GST_STATE_SUCCESS = 1,
|
||||
GST_STATE_ASYNC = 2,
|
||||
};
|
||||
|
||||
/* NOTE: this probably should be done with an #ifdef to decide
|
||||
* whether to safe-cast or to just do the non-checking cast.
|
||||
|
@ -150,6 +154,9 @@ struct _GstElement {
|
|||
guint16 numsinkpads;
|
||||
GList *pads;
|
||||
GstPad *select_pad;
|
||||
|
||||
GMutex *state_mutex;
|
||||
GCond *state_cond;
|
||||
};
|
||||
|
||||
struct _GstElementClass {
|
||||
|
@ -166,16 +173,19 @@ struct _GstElementClass {
|
|||
void (*new_pad) (GstElement *element, GstPad *pad);
|
||||
void (*pad_removed) (GstElement *element, GstPad *pad);
|
||||
void (*error) (GstElement *element, gchar *error);
|
||||
void (*event) (GstElement *element, GstEvent *event);
|
||||
void (*eos) (GstElement *element);
|
||||
|
||||
/* local pointers for get/set */
|
||||
void (*set_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
void (*get_property) (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
|
||||
/* vtable*/
|
||||
/* change the element state */
|
||||
GstElementStateReturn (*change_state) (GstElement *element);
|
||||
/* request a new pad */
|
||||
GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ, const gchar* name);
|
||||
void (*send_event) (GstElement *element, GstEvent *event);
|
||||
};
|
||||
|
||||
void gst_element_class_add_padtemplate (GstElementClass *klass, GstPadTemplate *templ);
|
||||
|
@ -214,6 +224,8 @@ void gst_element_disconnect (GstElement *src, const gchar *srcpadname,
|
|||
|
||||
void gst_element_signal_eos (GstElement *element);
|
||||
|
||||
void gst_element_send_event (GstElement *element, GstEvent *event);
|
||||
|
||||
|
||||
GstElementState gst_element_get_state (GstElement *element);
|
||||
gint gst_element_set_state (GstElement *element, GstElementState state);
|
||||
|
@ -222,7 +234,8 @@ void gst_element_wait_state_change (GstElement *element);
|
|||
|
||||
const gchar* gst_element_statename (GstElementState state);
|
||||
|
||||
void gst_element_error (GstElement *element, const gchar *error);
|
||||
void gst_element_info (GstElement *element, const gchar *info, ...);
|
||||
void gst_element_error (GstElement *element, const gchar *error, ...);
|
||||
|
||||
GstElementFactory* gst_element_get_factory (GstElement *element);
|
||||
|
||||
|
|
|
@ -77,6 +77,8 @@ gst_event_new (GstEventType type)
|
|||
|
||||
GST_DATA_TYPE (event) = _gst_event_type;
|
||||
GST_EVENT_TYPE (event) = type;
|
||||
GST_EVENT_TIMESTAMP (event) = 0LL;
|
||||
GST_EVENT_SRC (event) = NULL;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
@ -91,6 +93,16 @@ void
|
|||
gst_event_free (GstEvent* event)
|
||||
{
|
||||
g_mutex_lock (_gst_event_chunk_lock);
|
||||
if (GST_EVENT_SRC (event)) {
|
||||
gst_object_unref (GST_EVENT_SRC (event));
|
||||
}
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_INFO:
|
||||
gst_props_unref (GST_EVENT_INFO_PROPS (event));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_mem_chunk_free (_gst_event_chunk, event);
|
||||
g_mutex_unlock (_gst_event_chunk_lock);
|
||||
}
|
||||
|
@ -117,3 +129,49 @@ gst_event_new_seek (GstSeekType type, guint64 offset, gboolean flush)
|
|||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_event_new_info:
|
||||
* @props: The GstProps for this info event
|
||||
*
|
||||
* Allocate a new info event with the given props.
|
||||
*
|
||||
* Returns: A new info event.
|
||||
*/
|
||||
GstEvent*
|
||||
gst_event_new_info (const gchar *firstname, ...)
|
||||
{
|
||||
GstEvent *event;
|
||||
va_list var_args;
|
||||
|
||||
event = gst_event_new (GST_EVENT_INFO);
|
||||
va_start (var_args, firstname);
|
||||
|
||||
GST_EVENT_INFO_PROPS (event) = gst_props_newv (firstname, var_args);
|
||||
|
||||
va_end (var_args);
|
||||
|
||||
return event;
|
||||
}
|
||||
/**
|
||||
* gst_event_new_state_change:
|
||||
* @old: The old state
|
||||
* @state: The new state
|
||||
*
|
||||
* Allocate a new state change event with the given props.
|
||||
*
|
||||
* Returns: A new state change event.
|
||||
*/
|
||||
GstEvent*
|
||||
gst_event_new_state_change (GstElementState old, GstElementState state)
|
||||
{
|
||||
GstEvent *event;
|
||||
|
||||
event = gst_event_new (GST_EVENT_STATE_CHANGE);
|
||||
GST_EVENT_STATE_OLD (event) = old;
|
||||
GST_EVENT_STATE_NEW (event) = state;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,8 +24,11 @@
|
|||
#ifndef __GST_EVENT_H__
|
||||
#define __GST_EVENT_H__
|
||||
|
||||
#include <gst/gsttypes.h>
|
||||
#include <gst/gstelement.h>
|
||||
#include <gst/gstobject.h>
|
||||
#include <gst/gstdata.h>
|
||||
#include <gst/gstcaps.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -33,11 +36,16 @@ extern "C" {
|
|||
|
||||
typedef enum {
|
||||
GST_EVENT_UNKNOWN,
|
||||
/* horizontal events */
|
||||
GST_EVENT_EOS,
|
||||
GST_EVENT_FLUSH,
|
||||
GST_EVENT_EMPTY,
|
||||
GST_EVENT_SEEK,
|
||||
GST_EVENT_DISCONTINUOUS
|
||||
GST_EVENT_DISCONTINUOUS,
|
||||
/* vertical events */
|
||||
GST_EVENT_INFO,
|
||||
GST_EVENT_ERROR,
|
||||
GST_EVENT_STATE_CHANGE,
|
||||
} GstEventType;
|
||||
|
||||
extern GType _gst_event_type;
|
||||
|
@ -47,7 +55,8 @@ extern GType _gst_event_type;
|
|||
#define GST_IS_EVENT(event) (GST_DATA_TYPE(event) == GST_TYPE_EVENT)
|
||||
|
||||
#define GST_EVENT_TYPE(event) (GST_EVENT(event)->type)
|
||||
#define GST_EVENT_TIMESTAMP(event) (GST_EVENT(event)->timstamp)
|
||||
#define GST_EVENT_TIMESTAMP(event) (GST_EVENT(event)->timestamp)
|
||||
#define GST_EVENT_SRC(event) (GST_EVENT(event)->src)
|
||||
|
||||
/* seek events */
|
||||
typedef enum {
|
||||
|
@ -60,13 +69,18 @@ typedef enum {
|
|||
#define GST_EVENT_SEEK_OFFSET(event) (GST_EVENT(event)->event_data.seek.offset)
|
||||
#define GST_EVENT_SEEK_FLUSH(event) (GST_EVENT(event)->event_data.seek.flush)
|
||||
|
||||
typedef struct _GstEvent GstEvent;
|
||||
#define GST_EVENT_INFO_PROPS(event) (GST_EVENT(event)->event_data.info.props)
|
||||
|
||||
#define GST_EVENT_STATE_OLD(event) (GST_EVENT(event)->event_data.state.old_state)
|
||||
#define GST_EVENT_STATE_NEW(event) (GST_EVENT(event)->event_data.state.new_state)
|
||||
|
||||
|
||||
struct _GstEvent {
|
||||
GstData data;
|
||||
|
||||
GstEventType type;
|
||||
guint64 timestamp;
|
||||
GstObject *src;
|
||||
|
||||
union {
|
||||
struct {
|
||||
|
@ -74,6 +88,13 @@ struct _GstEvent {
|
|||
guint64 offset;
|
||||
gboolean flush;
|
||||
} seek;
|
||||
struct {
|
||||
GstProps *props;
|
||||
} info;
|
||||
struct {
|
||||
GstElementState old_state;
|
||||
GstElementState new_state;
|
||||
} state;
|
||||
} event_data;
|
||||
};
|
||||
|
||||
|
@ -88,6 +109,12 @@ GstEvent* gst_event_new_seek (GstSeekType type, guint64 offset, gboolean flush);
|
|||
/* flush events */
|
||||
#define gst_event_new_flush() gst_event_new(GST_EVENT_FLUSH)
|
||||
|
||||
/* info events */
|
||||
GstEvent* gst_event_new_info (const gchar *firstname, ...);
|
||||
|
||||
/* state change events */
|
||||
GstEvent* gst_event_new_state_change (GstElementState old, GstElementState state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "gsttype.h"
|
||||
#include "gstbin.h"
|
||||
#include "gstscheduler.h"
|
||||
#include "gstevent.h"
|
||||
|
||||
GType _gst_pad_type = 0;
|
||||
|
||||
|
@ -1671,8 +1672,8 @@ gst_padtemplate_class_init (GstPadTemplateClass *klass)
|
|||
gst_padtemplate_signals[TEMPL_PAD_CREATED] =
|
||||
g_signal_new ("pad_created", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstPadTemplateClass, pad_created), NULL, NULL,
|
||||
gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
|
||||
GST_TYPE_PAD);
|
||||
gst_marshal_VOID__POINTER, G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
|
||||
gstobject_class->path_string_separator = "*";
|
||||
|
@ -1969,6 +1970,7 @@ gst_pad_event_default (GstPad *pad, GstEvent *event)
|
|||
GstElement *element = GST_PAD_PARENT (pad);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH:
|
||||
case GST_EVENT_EOS:
|
||||
/* gst_element_signal_eos (element); */
|
||||
gst_element_set_state (element, GST_STATE_PAUSED);
|
||||
|
@ -2006,6 +2008,9 @@ gst_pad_send_event (GstPad *pad, GstEvent *event)
|
|||
|
||||
g_return_val_if_fail (event, FALSE);
|
||||
|
||||
if (GST_EVENT_SRC (event) == NULL)
|
||||
GST_EVENT_SRC (event) = gst_object_ref (GST_OBJECT (pad));
|
||||
|
||||
GST_DEBUG (GST_CAT_EVENT, "have event %d on pad %s:%s\n",
|
||||
GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <gst/gstbuffer.h>
|
||||
#include <gst/cothreads.h>
|
||||
#include <gst/gstcaps.h>
|
||||
#include <gst/gstevent.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "gstqueue.h"
|
||||
#include "gstscheduler.h"
|
||||
#include "gstevent.h"
|
||||
|
||||
GstElementDetails gst_queue_details = {
|
||||
"Queue",
|
||||
|
|
|
@ -13,5 +13,9 @@ typedef struct _GstBin GstBin;
|
|||
typedef struct _GstBinClass GstBinClass;
|
||||
typedef struct _GstScheduler GstScheduler;
|
||||
typedef struct _GstSchedulerClass GstSchedulerClass;
|
||||
typedef struct _GstEvent GstEvent;
|
||||
|
||||
typedef enum _GstElementState GstElementState;
|
||||
typedef enum _GstElementStateReturn GstElementStateReturn;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -226,9 +226,10 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
|
|||
}
|
||||
*/
|
||||
|
||||
if (!fakesink->silent)
|
||||
g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) %p\n",
|
||||
if (!fakesink->silent) {
|
||||
gst_element_info (GST_ELEMENT (fakesink), "chain ******* (%s:%s)< (%d bytes, %lld) %p",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
|
||||
}
|
||||
|
||||
g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
|
||||
|
||||
|
|
|
@ -300,6 +300,8 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
|||
srcpad = gst_pad_new_from_template (templ, name);
|
||||
gst_element_add_pad (GST_ELEMENT (fakesrc), srcpad);
|
||||
|
||||
g_free (name);
|
||||
|
||||
return srcpad;
|
||||
}
|
||||
|
||||
|
@ -312,7 +314,6 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
|||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
g_print("fakesrc: have seek event\n");
|
||||
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
||||
if (!GST_EVENT_SEEK_FLUSH (event)) {
|
||||
gst_event_free (event);
|
||||
|
@ -320,11 +321,9 @@ gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
|||
}
|
||||
/* else we do a flush too */
|
||||
case GST_EVENT_FLUSH:
|
||||
g_print("fakesrc: have flush event\n");
|
||||
src->need_flush = TRUE;
|
||||
break;
|
||||
default:
|
||||
g_print("fakesrc: have unhandled event\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -646,12 +645,10 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
if (src->need_flush) {
|
||||
src->need_flush = FALSE;
|
||||
g_print("fakesrc: sending FLUSH\n");
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
|
||||
}
|
||||
|
||||
if (src->rt_num_buffers == 0) {
|
||||
g_print("fakesrc: sending EOS\n");
|
||||
gst_element_set_state (GST_ELEMENT (src), GST_STATE_PAUSED);
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
@ -662,16 +659,17 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
if (src->eos) {
|
||||
GST_INFO (0, "fakesrc is setting eos on pad");
|
||||
g_print("fakesrc: sending EOS\n");
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
||||
buf = gst_fakesrc_create_buffer (src);
|
||||
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
|
||||
|
||||
if (!src->silent)
|
||||
g_print("fakesrc: get ******* (%s:%s)> (%d bytes, %llu) \n",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
if (!src->silent) {
|
||||
gst_element_info (GST_ELEMENT (src),
|
||||
"get ******* (%s:%s)> (%d bytes, %llu)",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
}
|
||||
|
||||
GST_DEBUG_ELEMENT (GST_CAT_DATAFLOW, src, "pre handoff emit\n");
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
|
@ -715,7 +713,6 @@ gst_fakesrc_loop(GstElement *element)
|
|||
}
|
||||
|
||||
if (src->eos) {
|
||||
GST_INFO (0, "fakesrc is setting eos on pad");
|
||||
gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
|
||||
return;
|
||||
}
|
||||
|
@ -723,9 +720,10 @@ gst_fakesrc_loop(GstElement *element)
|
|||
buf = gst_fakesrc_create_buffer (src);
|
||||
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
|
||||
|
||||
if (!src->silent)
|
||||
g_print("fakesrc: loop ******* (%s:%s) > (%d bytes, %llu) \n",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
if (!src->silent) {
|
||||
gst_element_info (element, "fakesrc: loop ******* (%s:%s) > (%d bytes, %llu)",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
}
|
||||
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
buf, pad);
|
||||
|
@ -768,9 +766,6 @@ gst_fakesrc_change_state (GstElement *element)
|
|||
break;
|
||||
}
|
||||
|
||||
if (GST_STATE_PENDING (element) == GST_STATE_READY) {
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "gstqueue.h"
|
||||
#include "gstscheduler.h"
|
||||
#include "gstevent.h"
|
||||
|
||||
GstElementDetails gst_queue_details = {
|
||||
"Queue",
|
||||
|
|
Loading…
Reference in a new issue