From fd1a66e8b5a6290b490741ef201a413d28e7de17 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 11 Oct 2005 11:08:52 +0000 Subject: [PATCH] docs/design/part-states.txt: Some more docs. Original commit message from CVS: * docs/design/part-states.txt: Some more docs. * gst/gstbin.c: (gst_bin_set_clock_func), (gst_bin_recalc_state), (gst_bin_change_state_func), (bin_bus_handler): Doc updates. Don't distribute the same clock over and over again. * gst/gstclock.c: * gst/gstclock.h: Doc updates. * gst/gstpad.c: (gst_flow_get_name), (gst_flow_to_quark), (gst_pad_get_type), (gst_pad_push), (gst_pad_push_event), (gst_pad_send_event): * gst/gstpad.h: Make probe emission threadsafe again. Register quarks and move _get_name() from utils. Doc updates. * gst/gstpipeline.c: (gst_pipeline_class_init), (gst_pipeline_change_state), (gst_pipeline_provide_clock_func): Only redistribute the clock of it changed. * gst/gstsystemclock.h: Doc updates. * gst/gstutils.c: * gst/gstutils.h: Moved the _flow_get_name() to GstPad. --- ChangeLog | 32 ++++++++++ docs/design/part-states.txt | 57 +++++++++++++++++- gst/gstbin.c | 15 ++--- gst/gstbin.h | 1 + gst/gstclock.c | 4 +- gst/gstclock.h | 1 + gst/gstpad.c | 138 ++++++++++++++++++++++++++++++-------------- gst/gstpad.h | 42 ++++++++++---- gst/gstpipeline.c | 6 +- gst/gstsystemclock.h | 1 + gst/gstutils.c | 35 ----------- gst/gstutils.h | 4 -- 12 files changed, 226 insertions(+), 110 deletions(-) diff --git a/ChangeLog b/ChangeLog index 192e504..0e9d3b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,35 @@ +2005-10-11 Wim Taymans + + * docs/design/part-states.txt: + Some more docs. + + * gst/gstbin.c: (gst_bin_set_clock_func), (gst_bin_recalc_state), + (gst_bin_change_state_func), (bin_bus_handler): + Doc updates. Don't distribute the same clock over and over again. + + * gst/gstclock.c: + * gst/gstclock.h: + Doc updates. + + * gst/gstpad.c: (gst_flow_get_name), (gst_flow_to_quark), + (gst_pad_get_type), (gst_pad_push), (gst_pad_push_event), + (gst_pad_send_event): + * gst/gstpad.h: + Make probe emission threadsafe again. + Register quarks and move _get_name() from utils. + Doc updates. + + * gst/gstpipeline.c: (gst_pipeline_class_init), + (gst_pipeline_change_state), (gst_pipeline_provide_clock_func): + Only redistribute the clock of it changed. + + * gst/gstsystemclock.h: + Doc updates. + + * gst/gstutils.c: + * gst/gstutils.h: + Moved the _flow_get_name() to GstPad. + 2005-10-11 Thomas Vander Stichele * check/gst-libs/gdp.c: (GST_START_TEST): diff --git a/docs/design/part-states.txt b/docs/design/part-states.txt index a3bc711..b1d6b63 100644 --- a/docs/design/part-states.txt +++ b/docs/design/part-states.txt @@ -286,6 +286,55 @@ Bin: Locking overview (element) -------------------------- +* Element commiting SUCCESS + + - STATE_LOCK is taken in set_state + - change state is called if SUCCESS, commit state is called + - commit state calls change_state to next state change. + - if final state is reached, stack unwinds and result is returned to + set_state and caller. + + + set_state(element) change_state (element) commit_state + + | | | + | | | + STATE_LOCK | | + | | | + |------------------------>| | + | | | + | | | + | | (do state change) | + | | | + | | | + | | if SUCCESS | + | |---------------------->| + | | | post message + | | | + | |<----------------------| if (!final) change_state (next) + | | | else SIGNAL + | | | + | | | + | | | + |<------------------------| | + | SUCCESS + | + STATE_UNLOCK + | + SUCCESS + + + +* Element commiting ASYNC + + - STATE_LOCK is taken in set_state + - change state is called and returns ASYNC + - ASYNC returned to the caller. + - element takes STATE_LOCK in streaming thread. + - element calls commit_state in streaming thread. + - commit state calls change_state to next state change. + + set_state(element) change_state (element) stream_thread commit_state (element) | | | | @@ -298,19 +347,21 @@ Locking overview (element) | | (start_task) | | | | | | | | STREAM_LOCK | - | | | | + | | |... | |<------------------------| | | - | ASYNC | | + | ASYNC STREAM_UNLOCK | STATE_UNLOCK | | | .....sync........ STATE_LOCK | ASYNC |----------------->| | | - | |---> post_message(ASYNC) + | |---> post_message() | |---> if (!final) change_state (next) | | else SIGNAL |<-----------------| STATE_UNLOCK | + STREAM_LOCK + | ... STREAM_UNLOCK diff --git a/gst/gstbin.c b/gst/gstbin.c index aa10368..1f9bfa6 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -51,7 +51,7 @@ * bin. Likewise the "element_removed" signal is fired whenever an element is * removed from the bin. * - * gst_bin_unref() is used to destroy the bin. + * gst_object_unref() is used to destroy the bin. */ #include "gst_private.h" @@ -70,11 +70,6 @@ GST_DEBUG_CATEGORY_STATIC (bin_debug); #define GST_CAT_DEFAULT bin_debug -#define GST_LOG_BIN_CONTENTS(bin, text) GST_LOG_OBJECT ((bin), \ - text ": %d elements: %u PLAYING, %u PAUSED, %u READY, %u NULL, own state: %s", \ - (bin)->numchildren, (guint) (bin)->child_states[3], \ - (guint) (bin)->child_states[2], (bin)->child_states[1], \ - (bin)->child_states[0], gst_element_state_get_name (GST_STATE (bin))) static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin", "Generic/Bin", @@ -351,10 +346,12 @@ gst_bin_set_clock_func (GstElement * element, GstClock * clock) bin = GST_BIN (element); GST_LOCK (bin); - for (children = bin->children; children; children = g_list_next (children)) { - GstElement *child = GST_ELEMENT (children->data); + if (element->clock != clock) { + for (children = bin->children; children; children = g_list_next (children)) { + GstElement *child = GST_ELEMENT (children->data); - gst_element_set_clock (child, clock); + gst_element_set_clock (child, clock); + } } GST_UNLOCK (bin); } diff --git a/gst/gstbin.h b/gst/gstbin.h index bc95399..e90066f 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -94,6 +94,7 @@ struct _GstBin { gboolean polling; gboolean state_dirty; + /*< private >*/ gpointer _gst_reserved[GST_PADDING]; }; diff --git a/gst/gstclock.c b/gst/gstclock.c index a25c9c9..695b6c9 100644 --- a/gst/gstclock.c +++ b/gst/gstclock.c @@ -31,8 +31,8 @@ * * The clock time is always measured in nanoseconds and always increases. The * pipeline uses the clock to calculate the stream time. - * Usually all renderers sync to the global clock using the buffer timestamps - * and the segment events. + * Usually all renderers sync to the global clock using the buffer timestamps, + * the newsegment events and the element's base time. * * The time of the clock in itself is not very usefull for an application. */ diff --git a/gst/gstclock.h b/gst/gstclock.h index cf5848d..4d8fb08 100644 --- a/gst/gstclock.h +++ b/gst/gstclock.h @@ -1,6 +1,7 @@ /* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans + * 2005 Wim Taymans * * gstclock.h: Header for clock subsystem * diff --git a/gst/gstpad.c b/gst/gstpad.c index 3475bc7..ca70a7e 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -73,17 +73,6 @@ #include "gstvalue.h" GST_DEBUG_CATEGORY_STATIC (debug_dataflow); -#define DEBUG_DATA(obj,data,notice) G_STMT_START{\ - if (!data) { \ - GST_CAT_DEBUG_OBJECT (debug_dataflow, obj, "NULL data value"); \ - } else if (GST_IS_EVENT (data)) { \ - GST_CAT_DEBUG_OBJECT (debug_dataflow, obj, "%s event %p (type %d, refcount %d)", notice, data, \ - GST_EVENT_TYPE (data), GST_DATA_REFCOUNT_VALUE (data)); \ - } else { \ - GST_CAT_LOG_OBJECT (debug_dataflow, obj, "%s buffer %p (size %u, refcount %d)", notice, data, \ - GST_BUFFER_SIZE (data), GST_BUFFER_REFCOUNT_VALUE (data)); \ - } \ -}G_STMT_END #define GST_CAT_DEFAULT GST_CAT_PADS /* Pad signals and args */ @@ -129,9 +118,71 @@ static xmlNodePtr gst_pad_save_thyself (GstObject * object, xmlNodePtr parent); static GstObjectClass *parent_class = NULL; static guint gst_pad_signals[LAST_SIGNAL] = { 0 }; +/* quarks for probe signals */ static GQuark buffer_quark; static GQuark event_quark; +typedef struct +{ + gint ret; + gchar *name; + GQuark quark; +} GstFlowQuarks; + +static GstFlowQuarks flow_quarks[] = { + {GST_FLOW_RESEND, "resend", 0}, + {GST_FLOW_OK, "ok", 0}, + {GST_FLOW_NOT_LINKED, "not-linked", 0}, + {GST_FLOW_WRONG_STATE, "wrong-state", 0}, + {GST_FLOW_UNEXPECTED, "unexpected", 0}, + {GST_FLOW_NOT_NEGOTIATED, "not-negotiated", 0}, + {GST_FLOW_ERROR, "error", 0}, + {GST_FLOW_NOT_SUPPORTED, "not-supported", 0}, + + {0, NULL, 0} +}; + +/** + * gst_flow_get_name: + * @ret: a #GstFlowReturn to get the name of. + * + * Gets a string representing the given flow return. + * + * Returns: a string with the name of the flow return. + */ +G_CONST_RETURN gchar * +gst_flow_get_name (GstFlowReturn ret) +{ + gint i; + + for (i = 0; flow_quarks[i].name; i++) { + if (ret == flow_quarks[i].ret) + return flow_quarks[i].name; + } + return "unknown"; +} + +/** + * gst_flow_to_quark: + * @ret: a #GstFlowReturn to get the quark of. + * + * Get the unique quark for the given GstFlowReturn. + * + * Returns: the quark associated with the flow return or 0 if an + * invalid return was specified. + */ +GQuark +gst_flow_to_quark (GstFlowReturn ret) +{ + gint i; + + for (i = 0; flow_quarks[i].name; i++) { + if (ret == flow_quarks[i].ret) + return flow_quarks[i].quark; + } + return 0; +} + GType gst_pad_get_type (void) { @@ -143,6 +194,7 @@ gst_pad_get_type (void) 0, (GInstanceInitFunc) gst_pad_init, NULL }; + gint i; _gst_pad_type = g_type_register_static (GST_TYPE_OBJECT, "GstPad", &pad_info, 0); @@ -150,6 +202,10 @@ gst_pad_get_type (void) buffer_quark = g_quark_from_static_string ("buffer"); event_quark = g_quark_from_static_string ("event"); + for (i = 0; flow_quarks[i].name; i++) { + flow_quarks[i].quark = g_quark_from_static_string (flow_quarks[i].name); + } + GST_DEBUG_CATEGORY_INIT (debug_dataflow, "GST_DATAFLOW", GST_DEBUG_BOLD | GST_DEBUG_FG_GREEN, "dataflow inside pads"); } @@ -3089,8 +3145,6 @@ gst_pad_push (GstPad * pad, GstBuffer * buffer) { GstPad *peer; GstFlowReturn ret; - gboolean emit_signal; - gboolean signal_ret = TRUE; g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); g_return_val_if_fail (GST_PAD_DIRECTION (pad) == GST_PAD_SRC, GST_FLOW_ERROR); @@ -3106,23 +3160,18 @@ gst_pad_push (GstPad * pad, GstBuffer * buffer) /* we emit signals on the pad arg, the peer will have a chance to * emit in the _chain() function */ - emit_signal = GST_PAD_DO_BUFFER_SIGNALS (pad) > 0; - GST_UNLOCK (pad); + if (G_UNLIKELY (GST_PAD_DO_BUFFER_SIGNALS (pad) > 0)) { + /* unlock before emitting */ + GST_UNLOCK (pad); - if (G_UNLIKELY (emit_signal)) { - signal_ret = gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer)); - } + /* if the signal handler returned FALSE, it means we should just drop the + * buffer */ + if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (buffer))) + goto dropped; - /* if the signal handler returned FALSE, it means we should just drop the - * buffer */ - if (signal_ret == FALSE) { - gst_buffer_unref (buffer); - GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return"); - return GST_FLOW_OK; + GST_LOCK (pad); } - GST_LOCK (pad); - if (G_UNLIKELY ((peer = GST_PAD_PEER (pad)) == NULL)) goto not_linked; gst_object_ref (peer); @@ -3135,6 +3184,12 @@ gst_pad_push (GstPad * pad, GstBuffer * buffer) return ret; /* ERROR recovery here */ +dropped: + { + gst_buffer_unref (buffer); + GST_DEBUG_OBJECT (pad, "Dropping buffer due to FALSE probe return"); + return GST_FLOW_OK; + } not_linked: { gst_buffer_unref (buffer); @@ -3382,25 +3437,20 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) { GstPad *peerpad; gboolean result; - gboolean emit_signal; - gboolean signal_ret = TRUE; g_return_val_if_fail (GST_IS_PAD (pad), FALSE); g_return_val_if_fail (event != NULL, FALSE); + g_return_val_if_fail (GST_IS_EVENT (event), FALSE); - emit_signal = GST_PAD_DO_EVENT_SIGNALS (pad) > 0; + GST_LOCK (pad); + if (G_UNLIKELY (GST_PAD_DO_EVENT_SIGNALS (pad) > 0)) { + GST_UNLOCK (pad); - if (G_UNLIKELY (emit_signal)) { - signal_ret = gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event)); - } + if (!gst_pad_emit_have_data_signal (pad, GST_MINI_OBJECT (event))) + goto dropping; - if (signal_ret == FALSE) { - GST_DEBUG_OBJECT (pad, "Dropping event after FALSE probe return"); - gst_event_unref (event); - return FALSE; + GST_LOCK (pad); } - - GST_LOCK (pad); peerpad = GST_PAD_PEER (pad); if (peerpad == NULL) goto not_linked; @@ -3415,6 +3465,12 @@ gst_pad_push_event (GstPad * pad, GstEvent * event) return result; /* ERROR handling */ +dropping: + { + GST_DEBUG_OBJECT (pad, "Dropping event after FALSE probe return"); + gst_event_unref (event); + return FALSE; + } not_linked: { gst_event_unref (event); @@ -3444,7 +3500,6 @@ gst_pad_send_event (GstPad * pad, GstEvent * event) g_return_val_if_fail (event != NULL, FALSE); GST_LOCK (pad); - if (GST_PAD_IS_SINK (pad) && !GST_EVENT_IS_DOWNSTREAM (event)) goto wrong_direction; if (GST_PAD_IS_SRC (pad) && !GST_EVENT_IS_UPSTREAM (event)) @@ -3482,8 +3537,6 @@ gst_pad_send_event (GstPad * pad, GstEvent * event) goto no_function; emit_signal = GST_PAD_DO_EVENT_SIGNALS (pad) > 0; - - gst_object_ref (pad); GST_UNLOCK (pad); if (G_UNLIKELY (emit_signal)) { @@ -3493,8 +3546,6 @@ gst_pad_send_event (GstPad * pad, GstEvent * event) result = eventfunc (GST_PAD_CAST (pad), event); - gst_object_unref (pad); - return result; /* ERROR handling */ @@ -3524,7 +3575,6 @@ flushing: dropping: { GST_DEBUG ("Dropping event after FALSE probe return"); - gst_object_unref (pad); gst_event_unref (event); return FALSE; } diff --git a/gst/gstpad.h b/gst/gstpad.h index 84444e3..31edaca 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -76,7 +76,7 @@ typedef enum { * @ret: the #GstPadLinkReturn value * * Macro to test if the given #GstPadLinkReturn value indicates a failed - * negotiation step (REFUSED/DELAYED). + * link step. */ #define GST_PAD_LINK_FAILED(ret) ((ret) < GST_PAD_LINK_OK) @@ -85,25 +85,47 @@ typedef enum { * @ret: the #GstPadLinkReturn value * * Macro to test if the given #GstPadLinkReturn value indicates a successfull - * negotiation step (OK/DONE). + * link step. */ #define GST_PAD_LINK_SUCCESSFUL(ret) ((ret) >= GST_PAD_LINK_OK) +/** + * GstFlowReturn: + * GST_FLOW_RESEND: Resend buffer, possibly with new caps. + * GST_FLOW_OK: Data passing was ok. + * GST_FLOW_NOT_LINKED: Pad is not linked. + * GST_FLOW_WRONG_STATE: Pad is in wrong state. + * GST_FLOW_UNEXPECTED: Did not expect anything, like after EOS. + * GST_FLOW_NOT_NEGOTIATED: Pad is not negotiated. + * GST_FLOW_ERROR: Some (fatal) error occured. + * + * The result of passing data to a linked pad. + */ typedef enum { - GST_FLOW_RESEND = 1, /* resend buffer, possibly with new caps */ - GST_FLOW_OK = 0, /* data passing was ok */ + GST_FLOW_RESEND = 1, + GST_FLOW_OK = 0, /* expected failures */ - GST_FLOW_NOT_LINKED = -1, /* pad is not linked */ - GST_FLOW_WRONG_STATE = -2, /* pad is in wrong state */ + GST_FLOW_NOT_LINKED = -1, + GST_FLOW_WRONG_STATE = -2, /* error cases */ - GST_FLOW_UNEXPECTED = -3, /* did not expect anything, like after EOS */ - GST_FLOW_NOT_NEGOTIATED = -4, /* pad is not negotiated */ - GST_FLOW_ERROR = -5, /* some (fatal) error occured */ - GST_FLOW_NOT_SUPPORTED = -6 /* function not supported */ + GST_FLOW_UNEXPECTED = -3, + GST_FLOW_NOT_NEGOTIATED = -4, + GST_FLOW_ERROR = -5, + GST_FLOW_NOT_SUPPORTED = -6 } GstFlowReturn; +/** + * GST_FLOW_IS_FATAL: + * @ret: a #GstFlowReturn value + * + * Macro to test if the given #GstFlowReturn value indicates a fatal + * error. + */ #define GST_FLOW_IS_FATAL(ret) ((ret) <= GST_FLOW_UNEXPECTED) +G_CONST_RETURN gchar* gst_flow_get_name (GstFlowReturn ret); +GQuark gst_flow_to_quark (GstFlowReturn ret); + typedef enum { GST_ACTIVATE_NONE, GST_ACTIVATE_PUSH, diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index 2e8fc90..a001931 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -324,10 +324,10 @@ gst_pipeline_change_state (GstElement * element, GstStateChange transition) GST_TIME_ARGS (start_time), GST_TIME_ARGS (element->base_time)); GST_UNLOCK (element); - /* now distribute the clock */ - gst_element_set_clock (element, clock); - if (new_clock) { + /* now distribute the clock */ + gst_element_set_clock (element, clock); + /* if we selected a new clock, let the app know about it */ gst_element_post_message (element, gst_message_new_new_clock (GST_OBJECT_CAST (element), clock)); diff --git a/gst/gstsystemclock.h b/gst/gstsystemclock.h index 4e02c1f..892b3f4 100644 --- a/gst/gstsystemclock.h +++ b/gst/gstsystemclock.h @@ -1,6 +1,7 @@ /* GStreamer * Copyright (C) 1999,2000 Erik Walthinsen * 2000 Wim Taymans + * 2005 Wim Taymans * * gstsystemclock.h: A clock implementation based on system time * diff --git a/gst/gstutils.c b/gst/gstutils.c index 76d71ae..7c4fa17 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -1784,41 +1784,6 @@ gst_pad_get_parent_element (GstPad * pad) } /** - * gst_flow_get_name: - * @ret: a #GstFlowReturn to get the name of. - * - * Gets a string representing the given flow return. - * - * Returns: a string with the name of the flow return. - */ -G_CONST_RETURN gchar * -gst_flow_get_name (GstFlowReturn ret) -{ - switch (ret) { - case GST_FLOW_RESEND: - return "RESEND_BUFFER"; - case GST_FLOW_OK: - return "OK"; - /* expected failures */ - case GST_FLOW_NOT_LINKED: - return "NOT_LINKED"; - case GST_FLOW_WRONG_STATE: - return "WRONG_STATE"; - /* error cases */ - case GST_FLOW_UNEXPECTED: - return "UNEXPECTED"; - case GST_FLOW_NOT_NEGOTIATED: - return "NOT_NEGOTIATED"; - case GST_FLOW_ERROR: - return "ERROR"; - case GST_FLOW_NOT_SUPPORTED: - return "NOT_SUPPORTED"; - default: - return "UNKNOWN error"; - } -} - -/** * gst_object_default_error: * @source: the #GstObject that initiated the error. * @error: the GError. diff --git a/gst/gstutils.h b/gst/gstutils.h index 1a300c3..00194f2 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -529,10 +529,6 @@ gboolean gst_pad_proxy_setcaps (GstPad * pad, GstCaps * caps); GstElement* gst_pad_get_parent_element (GstPad *pad); -/* flow */ -G_CONST_RETURN gchar* gst_flow_get_name (GstFlowReturn ret); - - /* util query functions */ gboolean gst_pad_query_position (GstPad *pad, GstFormat *format, gint64 *cur, gint64 *end); -- 2.7.4