From eb6c33fb23d4f1d2e25ca151f61c95eaea5ef42f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 1 Jan 2003 03:09:39 +0000 Subject: [PATCH] - Added PAD_NEGOTIATING flag, remove PAD_EOS flag Original commit message from CVS: - Added PAD_NEGOTIATING flag, remove PAD_EOS flag - Try to avoid negotiation in state change if pad were already negotiating - Added gstquery.c for completeness (maybe merge common functions with gstformat.c?) --- gst/Makefile.am | 1 + gst/elements/gstpipefilter.c | 2 - gst/gst.c | 1 + gst/gstelement.c | 5 + gst/gstpad.c | 33 +++--- gst/gstpad.h | 2 +- gst/gstquery.c | 176 +++++++++++++++++++++++++++++++ gst/gstquery.h | 29 ++++- plugins/elements/gstpipefilter.c | 2 - 9 files changed, 231 insertions(+), 20 deletions(-) create mode 100644 gst/gstquery.c diff --git a/gst/Makefile.am b/gst/Makefile.am index 7eae6501d1..dcea04371f 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -75,6 +75,7 @@ libgstreamer_@GST_MAJORMINOR@_la_SOURCES = \ gstprobe.c \ gstprops.c \ gstqueue.c \ + gstquery.c \ gstscheduler.c \ gstsystemclock.c \ gstthread.c \ diff --git a/gst/elements/gstpipefilter.c b/gst/elements/gstpipefilter.c index 77fe738d08..7ac2d5f456 100644 --- a/gst/elements/gstpipefilter.c +++ b/gst/elements/gstpipefilter.c @@ -147,8 +147,6 @@ gst_pipefilter_handle_event (GstPad *pad, GstEvent *event) if (close (pipefilter->fdout[0]) < 0) perror("close"); - GST_FLAG_SET (pad, GST_PAD_EOS); - return TRUE; } diff --git a/gst/gst.c b/gst/gst.c index edac075e82..7f1e7a4867 100644 --- a/gst/gst.c +++ b/gst/gst.c @@ -441,6 +441,7 @@ init_post (void) GST_VERSION, _gst_use_threads?"":"(no threads)"); _gst_format_initialize (); + _gst_query_type_initialize (); gst_object_get_type (); gst_pad_get_type (); gst_real_pad_get_type (); diff --git a/gst/gstelement.c b/gst/gstelement.c index 18015048d3..9f454df4f6 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -2190,6 +2190,11 @@ gst_element_negotiate_pads (GstElement *element) if (!parent) continue; + /* skips pads that were already negotiating */ + if (GST_FLAG_IS_SET (sinkpad, GST_PAD_NEGOTIATING) || + GST_FLAG_IS_SET (srcpad, GST_PAD_NEGOTIATING)) + continue; + otherstate = GST_STATE (parent); /* swap pads if needed */ diff --git a/gst/gstpad.c b/gst/gstpad.c index 617d5fede8..62296f5d17 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -215,6 +215,7 @@ gst_real_pad_init (GstRealPad *pad) pad->querytypefunc = gst_pad_get_query_types_default; GST_FLAG_SET (pad, GST_PAD_DISABLED); + GST_FLAG_UNSET (pad, GST_PAD_NEGOTIATING); gst_probe_dispatcher_init (&pad->probedisp); } @@ -988,26 +989,22 @@ gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps) GST_INFO (GST_CAT_PADS, "*actually* connecting %s:%s and %s:%s", GST_DEBUG_PAD_NAME (realsrc), GST_DEBUG_PAD_NAME (realsink)); } - if (GST_RPAD_PEER (realsrc) != NULL) - { + if (GST_RPAD_PEER (realsrc) != NULL) { GST_INFO (GST_CAT_PADS, "Real source pad %s:%s has a peer, failed", GST_DEBUG_PAD_NAME (realsrc)); return FALSE; } - if (GST_RPAD_PEER (realsink) != NULL) - { + if (GST_RPAD_PEER (realsink) != NULL) { GST_INFO (GST_CAT_PADS, "Real sink pad %s:%s has a peer, failed", GST_DEBUG_PAD_NAME (realsink)); return FALSE; } - if (GST_PAD_PARENT (realsrc) == NULL) - { + if (GST_PAD_PARENT (realsrc) == NULL) { GST_INFO (GST_CAT_PADS, "Real src pad %s:%s has no parent, failed", GST_DEBUG_PAD_NAME (realsrc)); return FALSE; } - if (GST_PAD_PARENT (realsink) == NULL) - { + if (GST_PAD_PARENT (realsink) == NULL) { GST_INFO (GST_CAT_PADS, "Real src pad %s:%s has no parent, failed", GST_DEBUG_PAD_NAME (realsrc)); return FALSE; @@ -1028,15 +1025,12 @@ gst_pad_connect_filtered (GstPad *srcpad, GstPad *sinkpad, GstCaps *filtercaps) realsrc = realsink; realsink = temppad; } - if (GST_PAD_PARENT (realsink) == NULL) - if (GST_RPAD_DIRECTION (realsrc) != GST_PAD_SRC) - { + if (GST_RPAD_DIRECTION (realsrc) != GST_PAD_SRC) { GST_INFO (GST_CAT_PADS, "Real src pad %s:%s is not a source pad, failed", GST_DEBUG_PAD_NAME (realsrc)); return FALSE; } - if (GST_RPAD_DIRECTION (realsink) != GST_PAD_SINK) - { + if (GST_RPAD_DIRECTION (realsink) != GST_PAD_SINK) { GST_INFO (GST_CAT_PADS, "Real sink pad %s:%s is not a sink pad, failed", GST_DEBUG_PAD_NAME (realsink)); return FALSE; @@ -1283,7 +1277,7 @@ gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify) g_return_val_if_fail (pad != NULL, GST_PAD_CONNECT_REFUSED); g_return_val_if_fail (GST_IS_PAD (pad), GST_PAD_CONNECT_REFUSED); - + /* if this pad has a parent and the parent is not READY, delay the * negotiation */ if (parent && GST_STATE (parent) < GST_STATE_READY) @@ -1330,13 +1324,24 @@ gst_pad_try_set_caps_func (GstRealPad *pad, GstCaps *caps, gboolean notify) if (notify && GST_RPAD_CONNECTFUNC (pad)) { GstPadConnectReturn res; gchar *debug_string; + gboolean negotiating; GST_INFO (GST_CAT_CAPS, "calling connect function on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + negotiating = GST_FLAG_IS_SET (pad, GST_PAD_NEGOTIATING); + + /* set the NEGOTIATING flag if not already done */ + if (!negotiating) + GST_FLAG_SET (pad, GST_PAD_NEGOTIATING); + /* call the connect function */ res = GST_RPAD_CONNECTFUNC (pad) (GST_PAD (pad), caps); + /* unset again after negotiating only if we set it */ + if (!negotiating) + GST_FLAG_UNSET (pad, GST_PAD_NEGOTIATING); + switch (res) { case GST_PAD_CONNECT_REFUSED: debug_string = "REFUSED"; diff --git a/gst/gstpad.h b/gst/gstpad.h index 54e6e458a1..03a8a79c81 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -160,7 +160,7 @@ typedef enum { typedef enum { GST_PAD_DISABLED = GST_OBJECT_FLAG_LAST, - GST_PAD_EOS, + GST_PAD_NEGOTIATING, GST_PAD_FLAG_LAST = GST_OBJECT_FLAG_LAST + 4 } GstPadFlags; diff --git a/gst/gstquery.c b/gst/gstquery.c new file mode 100644 index 0000000000..64c3bf16f9 --- /dev/null +++ b/gst/gstquery.c @@ -0,0 +1,176 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstquery.c: GstQueryType registration + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include "gstlog.h" + +#include "gstquery.h" + +static GList *_gst_queries = NULL; +static GHashTable *_nick_to_query = NULL; +static GHashTable *_query_type_to_nick = NULL; +static gint _n_values = 1; /* we start from 1 because 0 reserved for NONE */ + +static GstQueryTypeDefinition standard_definitions[] = { + { GST_QUERY_TOTAL, "total", "Total length" }, + { GST_QUERY_POSITION, "position", "Current Position" }, + { GST_QUERY_LATENCY, "latency", "Latency" }, + { GST_QUERY_JITTER, "jitter", "Jitter" }, + { GST_QUERY_START, "start", "Start position of stream" }, + { GST_QUERY_SEGMENT_END, "segment_end", "End position of the stream" }, + { GST_QUERY_RATE, "rate", "Configured rate 1000000 = 1" }, + { 0, NULL, NULL } +}; + +void +_gst_query_type_initialize (void) +{ + GstQueryTypeDefinition *standards = standard_definitions; + + if (_nick_to_query == NULL) { + _nick_to_query = g_hash_table_new (g_str_hash, g_str_equal); + _query_type_to_nick = g_hash_table_new (NULL, NULL); + } + + while (standards->nick) { + g_hash_table_insert (_nick_to_query, standards->nick, standards); + g_hash_table_insert (_query_type_to_nick, GINT_TO_POINTER (standards->value), standards); + + _gst_queries = g_list_append (_gst_queries, standards); + standards++; + _n_values++; + } +} + +/** + * gst_query_type_register: + * @nick: The nick of the new query + * @description: The description of the new query + * + * Create a new GstQueryType based on the nick or return an + * allrady registered query with that nick + * + * Returns: A new GstQueryType or an already registered query + * with the same nick. + */ +GstQueryType +gst_query_type_register (const gchar *nick, const gchar *description) +{ + GstQueryTypeDefinition *query; + GstQueryType lookup; + + g_return_val_if_fail (nick != NULL, 0); + g_return_val_if_fail (description != NULL, 0); + + lookup = gst_query_type_get_by_nick (nick); + if (lookup != GST_QUERY_NONE) + return lookup; + + query = g_new0 (GstQueryTypeDefinition, 1); + query->value = _n_values; + query->nick = g_strdup (nick); + query->description = g_strdup (description); + + g_hash_table_insert (_nick_to_query, query->nick, query); + g_hash_table_insert (_query_type_to_nick, GINT_TO_POINTER (query->value), query); + _gst_queries = g_list_append (_gst_queries, query); + _n_values++; + + return query->value; +} + +/** + * gst_query_type_get_by_nick: + * @nick: The nick of the query + * + * Return the query registered with the given nick. + * + * Returns: The query with @nick or GST_QUERY_NONE + * if the query was not registered. + */ +GstQueryType +gst_query_type_get_by_nick (const gchar *nick) +{ + GstQueryTypeDefinition *query; + + g_return_val_if_fail (nick != NULL, 0); + + query = g_hash_table_lookup (_nick_to_query, nick); + + if (query != NULL) + return query->value; + else + return GST_QUERY_NONE; +} + +/** + * gst_queries_contains: + * @queries: The query array to search + * @query: the query to find + * + * See if the given query is inside the query array. + * + * Returns: TRUE if the query is found inside the array + */ +gboolean +gst_queries_contains (const GstQueryType *queries, GstQueryType query) +{ + if (!queries) + return FALSE; + + while (*queries) { + if (*queries == query) + return TRUE; + + queries++; + } + return FALSE; +} + + +/** + * gst_query_type_get_details: + * @query: The query to get details of + * + * Get details about the given query. + * + * Returns: The #GstQueryTypeDefinition for @query or NULL on failure. + */ +const GstQueryTypeDefinition* +gst_query_type_get_details (GstQueryType query) +{ + return g_hash_table_lookup (_query_type_to_nick, GINT_TO_POINTER (query)); +} + +/** + * gst_query_type_get_definitions: + * + * Get a list of all the registered query types. + * + * Returns: A GList of #GstQueryTypeDefinition. + */ +const GList* +gst_query_type_get_definitions (void) +{ + return _gst_queries; +} diff --git a/gst/gstquery.h b/gst/gstquery.h index 96d64aef13..dbe9fc3043 100644 --- a/gst/gstquery.h +++ b/gst/gstquery.h @@ -24,7 +24,7 @@ #ifndef __GST_QUERY_H__ #define __GST_QUERY_H__ -#include +#include G_BEGIN_DECLS @@ -39,6 +39,18 @@ typedef enum { GST_QUERY_RATE } GstQueryType; +/* rate is relative to 1000000LL */ +#define GST_QUERY_TYPE_RATE_DEN 1000000LL + +typedef struct _GstQueryTypeDefinition GstQueryTypeDefinition; + +struct _GstQueryTypeDefinition +{ + GstQueryType value; + gchar *nick; + gchar *description; +}; + #ifdef G_HAVE_ISO_VARARGS #define GST_QUERY_TYPE_FUNCTION(type, functionname, ...) \ static const GstQueryType* \ @@ -63,6 +75,21 @@ functionname (type object) \ } #endif +void _gst_query_type_initialize (void); + +/* register a new query */ +GstQueryType gst_query_type_register (const gchar *nick, + const gchar *description); +GstQueryType gst_query_type_get_by_nick (const gchar *nick); + +/* check if a query is in an array of querys */ +gboolean gst_query_types_contains (const GstQueryType *types, GstQueryType type); + +/* query for query details */ +const GstQueryTypeDefinition* + gst_query_type_get_details (GstQueryType type); +const GList* gst_query_type_get_definitions (void); + G_END_DECLS #endif /* __GST_QUERY_H__ */ diff --git a/plugins/elements/gstpipefilter.c b/plugins/elements/gstpipefilter.c index 77fe738d08..7ac2d5f456 100644 --- a/plugins/elements/gstpipefilter.c +++ b/plugins/elements/gstpipefilter.c @@ -147,8 +147,6 @@ gst_pipefilter_handle_event (GstPad *pad, GstEvent *event) if (close (pipefilter->fdout[0]) < 0) perror("close"); - GST_FLAG_SET (pad, GST_PAD_EOS); - return TRUE; }