author | Tim-Philipp Müller <tim.muller@collabora.co.uk> | |
Thu, 16 Jun 2011 16:27:21 +0000 (17:27 +0100) | ||
committer | Tim-Philipp Müller <tim.muller@collabora.co.uk> | |
Sat, 18 Jun 2011 11:47:37 +0000 (12:47 +0100) |
Merge remote-tracking branch 'origin/0.10.35'
105 files changed:
index 46dfcea233cf6df83e3771d8a8066e87d614f893..69b981f10caa234ad0ff639179d0fda8505bd94b 160000 (submodule)
--- a/common
+++ b/common
-Subproject commit 46dfcea233cf6df83e3771d8a8066e87d614f893
+Subproject commit 69b981f10caa234ad0ff639179d0fda8505bd94b
diff --git a/configure.ac b/configure.ac
index f625f86a626d3cfd54bc650bacac811865b755ff..0a03ccdd9dd7cd2dbe2a98d702fca61e82c73df8 100644 (file)
--- a/configure.ac
+++ b/configure.ac
dnl initialize autoconf
dnl when going to/from release please set the nano (fourth number) right !
dnl releases only do Wall, git and prerelease does Werror too
-AC_INIT(GStreamer, 0.10.35,
+AC_INIT(GStreamer, 0.10.35.1,
http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer,
gstreamer)
AG_GST_INIT
dnl *** checks for dependency libraries ***
dnl GLib
-GLIB_REQ=2.22
+GLIB_REQ=2.24
AG_GST_GLIB_CHECK([$GLIB_REQ])
diff --git a/docs/faq/general.xml b/docs/faq/general.xml
index 1e6641cf3030ac39f3f2b7264b6e01fae6943ced..60e9b7ddcc9affb5963be0e8e7f86e2520aa9199 100644 (file)
--- a/docs/faq/general.xml
+++ b/docs/faq/general.xml
GStreamer aims to support every format imaginable, but that doesn't mean the
developers have managed to achieve that aim yet. If a GStreamer enabled
application doesn't play back your files, you can help us solve that problem
-by <ulink url="htpp://bugzilla.gnome.org">filing an enhancement request
+by <ulink url="http://bugzilla.gnome.org">filing an enhancement request
bug</ulink> for that format. If you have it, please provide:
<itemizedlist>
<listitem><para>links to other players, preferrably Open Source and working
index e1eba92c66580b38bf674376a5dc1f4be3af17c7..c29ac0531a9a052742a1dbecd5d81ceb8d8d7ccf 100644 (file)
gst_caps_is_equal_fixed
gst_caps_is_always_compatible
gst_caps_is_subset
+gst_caps_is_subset_structure
gst_caps_can_intersect
gst_caps_intersect
gst_caps_intersect_full
<SECTION>
<FILE>gstghostpad</FILE>
<TITLE>GstGhostPad</TITLE>
+GstProxyPad
GstGhostPad
+
gst_ghost_pad_new
gst_ghost_pad_new_no_target
gst_ghost_pad_new_from_template
gst_ghost_pad_new_no_target_from_template
+
gst_ghost_pad_set_target
gst_ghost_pad_get_target
+
gst_ghost_pad_construct
+
+gst_ghost_pad_setcaps_default
+gst_ghost_pad_unlink_default
+gst_ghost_pad_link_default
+gst_ghost_pad_activate_pull_default
+gst_ghost_pad_activate_push_default
+
+gst_ghost_pad_internal_activate_push_default
+gst_ghost_pad_internal_activate_pull_default
+
+gst_proxy_pad_get_internal
+
+gst_proxy_pad_query_type_default
+gst_proxy_pad_event_default
+gst_proxy_pad_query_default
+gst_proxy_pad_iterate_internal_links_default
+gst_proxy_pad_bufferalloc_default
+gst_proxy_pad_chain_default
+gst_proxy_pad_chain_list_default
+gst_proxy_pad_getrange_default
+gst_proxy_pad_checkgetrange_default
+gst_proxy_pad_getcaps_default
+gst_proxy_pad_acceptcaps_default
+gst_proxy_pad_fixatecaps_default
+gst_proxy_pad_setcaps_default
+gst_proxy_pad_unlink_default
<SUBSECTION Standard>
GstGhostPadClass
GST_GHOST_PAD
GST_PROXY_PAD_CLASS
GST_TYPE_PROXY_PAD
GstGhostPadPrivate
-GstProxyPad
GstProxyPadClass
GstProxyPadPrivate
gst_proxy_pad_get_type
GstMiniObjectFlags
GstMiniObjectCopyFunction
GstMiniObjectFinalizeFunction
+GstMiniObjectWeakNotify
GST_MINI_OBJECT_FLAGS
GST_MINI_OBJECT_FLAG_IS_SET
gst_mini_object_unref
gst_mini_object_replace
+gst_mini_object_weak_ref
+gst_mini_object_weak_unref
+
GstParamSpecMiniObject
gst_param_spec_mini_object
gst_structure_n_fields
gst_structure_has_field
gst_structure_has_field_typed
+gst_structure_is_equal
+gst_structure_is_subset
+gst_structure_can_intersect
+gst_structure_intersect
gst_structure_id_has_field
gst_structure_id_has_field_typed
gst_structure_get_boolean
index 1a43266590fbab37ceefdd56ad6f986ba053e10e..621cbbdae29c219101d2e1ef40c7c55042fa94a9 100644 (file)
gst_base_src_set_blocksize
gst_base_src_get_do_timestamp
gst_base_src_set_do_timestamp
+gst_base_src_set_dynamic_size
gst_base_src_new_seamless_segment
GST_BASE_SRC_PAD
index 75548b2bcdb9c824ea0da5671c313ed5739b8a3c..fd88bb8cae32226a10b3cb75a4949fa2960155ba 100644 (file)
<ARG>
<NAME>GstFakeSink::num-buffers</NAME>
<TYPE>gint</TYPE>
-<RANGE>>= G_MAXULONG</RANGE>
+<RANGE>>= -1</RANGE>
<FLAGS>rw</FLAGS>
<NICK>num-buffers</NICK>
<BLURB>Number of buffers to accept going EOS.</BLURB>
<DEFAULT>FALSE</DEFAULT>
</ARG>
+<ARG>
+<NAME>GstMultiQueue::sync-by-running-time</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Sync By Running Time</NICK>
+<BLURB>Synchronize deactivated or not-linked streams by running time.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
<ARG>
<NAME>GstBin::async-handling</NAME>
<TYPE>gboolean</TYPE>
<DEFAULT>FALSE</DEFAULT>
</ARG>
+<ARG>
+<NAME>GstInputSelector::sync-streams</NAME>
+<TYPE>gboolean</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Sync Streams</NICK>
+<BLURB>Synchronize inactive streams to the running time of the active stream.</BLURB>
+<DEFAULT>FALSE</DEFAULT>
+</ARG>
+
index 4201ecb5b206ceba8c052543b2bec540209c105f..ea81e4aad7568f7890310da70748a78b3c6deb89 100644 (file)
GObject
GstObject
- GstPad
- GstPadTemplate
- GstPluginFeature
- GstElementFactory
- GstTypeFindFactory
- GstIndexFactory
+ GstBus
+ GstClock
GstElement
- GstBin
- GstPipeline
- GstBaseTransform
- GstCapsFilter
- GstIdentity
- GstBaseSrc
- GstFakeSrc
- GstPushSrc
- GstFdSrc
- GstFileSrc
GstBaseSink
GstFakeSink
GstFdSink
GstFileSink
+ GstBaseSrc
+ GstFakeSrc
+ GstFileSrc
+ GstPushSrc
+ GstFdSrc
+ GstBaseTransform
+ GstCapsFilter
+ GstIdentity
+ GstBin
+ GstPipeline
GstFunnel
GstInputSelector
+ GstMultiQueue
GstOutputSelector
GstQueue
GstQueue2
GstTee
GstTypeFindElement
- GstMultiQueue
GstValve
- GstBus
- GstTask
- GstTaskPool
- GstClock
- GstPlugin
- GstRegistry
GstIndex
GstMemIndex
- GstFileIndex
+ GstPad
+ GstPadTemplate
+ GstPlugin
+ GstPluginFeature
+ GstElementFactory
+ GstIndexFactory
+ GstTypeFindFactory
+ GstRegistry
+ GstTask
+ GstTaskPool
GstSignalObject
GInterface
GTypePlugin
index 0245303682047ae567ec0b77aec773cbc4e0af9f..03805f5be2c57d0fbf6c779f4a892033ea06812b 100644 (file)
GstBin GstChildProxy
-GstPipeline GstChildProxy
-GstFdSrc GstURIHandler
-GstFileSrc GstURIHandler
GstFdSink GstURIHandler
+GstFdSrc GstURIHandler
GstFileSink GstURIHandler
+GstFileSrc GstURIHandler
+GstPipeline GstChildProxy
diff --git a/docs/plugins/inspect/plugin-coreelements.xml b/docs/plugins/inspect/plugin-coreelements.xml
index 50ea185af9bc5e0ef8bb937279cf25af9e3f2586..e99c7802aaafe62e25196c916158baa09b34829e 100644 (file)
<description>standard GStreamer elements</description>
<filename>../../plugins/elements/.libs/libgstcoreelements.so</filename>
<basename>libgstcoreelements.so</basename>
- <version>0.10.35</version>
+ <version>0.10.35.1</version>
<license>LGPL</license>
<source>gstreamer</source>
- <package>GStreamer source release</package>
+ <package>GStreamer git</package>
<origin>Unknown package origin</origin>
<elements>
<element>
</pads>
</element>
</elements>
-</plugin>
\ No newline at end of file
+</plugin>
diff --git a/docs/plugins/inspect/plugin-coreindexers.xml b/docs/plugins/inspect/plugin-coreindexers.xml
index b7741d07e5b56da775a1f7191ab3da648ef5ff58..80f072e2a5999959017ef76a61fa0d81c92b943b 100644 (file)
<description>GStreamer core indexers</description>
<filename>../../plugins/indexers/.libs/libgstcoreindexers.so</filename>
<basename>libgstcoreindexers.so</basename>
- <version>0.10.35</version>
+ <version>0.10.35.1</version>
<license>LGPL</license>
<source>gstreamer</source>
- <package>GStreamer source release</package>
+ <package>GStreamer git</package>
<origin>Unknown package origin</origin>
<elements>
</elements>
-</plugin>
\ No newline at end of file
+</plugin>
diff --git a/docs/random/release b/docs/random/release
index 6a8a3779e323afe44aaa2f449a7b1c0f1846e2f2..f45bf97c1b17d8405f8d1bacc46bae1256233433 100644 (file)
--- a/docs/random/release
+++ b/docs/random/release
+ e.g:
scp gstreamer-0.10.42.tar.gz master.gnome.org:
ssh master.gnome.org
- install-module gstreamer-0.10.42.tar.gz
+ ftpadmin install gstreamer-0.10.42.tar.gz
- Send release announcements to:
gstreamer-devel@lists.sourceforge.net gstreamer-announce@lists.sourceforge.net kde-multimedia@kde.org gnome-multimedia@gnome.org
diff --git a/gst/gst_private.h b/gst/gst_private.h
index 2cafbee61102bfd96654f6b0d6bddc44f31375a5..6bd67250fc7051a9bbb933bd22fed65ea560629a 100644 (file)
--- a/gst/gst_private.h
+++ b/gst/gst_private.h
/* for the pad cache */
#include "gstpad.h"
+/* for GstElement */
+#include "gstelement.h"
+
G_BEGIN_DECLS
/* used by gstparse.c and grammar.y */
void _priv_gst_pad_invalidate_cache (GstPad *pad);
+/* Used in GstBin for manual state handling */
+void _priv_gst_element_state_changed (GstElement *element, GstState oldstate,
+ GstState newstate, GstState pending);
+
/* used in both gststructure.c and gstcaps.c; numbers are completely made up */
#define STRUCTURE_ESTIMATED_STRING_LEN(s) (16 + (s)->fields->len * 22)
#endif
+#ifdef GST_DISABLE_DEPRECATED
+typedef GList* (*GstPadIntLinkFunction) (GstPad *pad);
+#endif
+
+
G_END_DECLS
#endif /* __GST_PRIVATE_H__ */
diff --git a/gst/gstbin.c b/gst/gstbin.c
index 73758213e96aecac9d066b709d590e96374d9dd4..89ad34e721855fdc118ab6efb73dc04960520376 100644 (file)
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
GstIndex *index;
/* forward messages from our children */
gboolean message_forward;
+
+ gboolean posted_eos;
};
typedef struct
static GstStateChangeReturn gst_bin_change_state_func (GstElement * element,
GstStateChange transition);
+static void gst_bin_state_changed (GstElement * element, GstState oldstate,
+ GstState newstate, GstState pending);
static GstStateChangeReturn gst_bin_get_state_func (GstElement * element,
GstState * state, GstState * pending, GstClockTime timeout);
static void bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
gboolean flag_pending);
static void bin_handle_async_start (GstBin * bin, gboolean new_base_time);
static void bin_push_state_continue (BinContinueData * data);
+static void bin_do_eos (GstBin * bin);
static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_bin_change_state_func);
+ gstelement_class->state_changed = GST_DEBUG_FUNCPTR (gst_bin_state_changed);
gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state_func);
gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_bin_get_index_func);
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
*
* call with bin LOCK */
static gboolean
-is_eos (GstBin * bin)
+is_eos (GstBin * bin, guint32 * seqnum)
{
gboolean result;
- GList *walk;
+ gint n_eos = 0;
+ GList *walk, *msgs;
result = TRUE;
for (walk = bin->children; walk; walk = g_list_next (walk)) {
element = GST_ELEMENT_CAST (walk->data);
if (bin_element_is_sink (element, bin) == 0) {
/* check if element posted EOS */
- if (find_message (bin, GST_OBJECT_CAST (element), GST_MESSAGE_EOS)) {
+ if ((msgs =
+ find_message (bin, GST_OBJECT_CAST (element), GST_MESSAGE_EOS))) {
GST_DEBUG ("sink '%s' posted EOS", GST_ELEMENT_NAME (element));
+ *seqnum = gst_message_get_seqnum (GST_MESSAGE_CAST (msgs->data));
+ n_eos++;
} else {
GST_DEBUG ("sink '%s' did not post EOS yet",
GST_ELEMENT_NAME (element));
}
}
}
- return result;
+ /* FIXME: Some tests (e.g. elements/capsfilter) use
+ * pipelines with a dangling sinkpad but no sink element.
+ * These tests assume that no EOS message is ever
+ * posted on the bus so let's keep that behaviour.
+ * In valid pipelines this doesn't make a difference.
+ */
+ return result && n_eos > 0;
}
static void
}
/* gst_iterator_fold functions for pads_activate
- * Note how we don't stop the iterator when we fail an activation. This is
- * probably a FIXME since when one pad activation fails, we don't want to
- * continue our state change. */
+ * Stop the iterator if activating one pad failed. */
static gboolean
activate_pads (GstPad * pad, GValue * ret, gboolean * active)
{
- if (!gst_pad_set_active (pad, *active))
+ gboolean cont = TRUE;
+
+ if (!(cont = gst_pad_set_active (pad, *active)))
g_value_set_boolean (ret, FALSE);
else if (!*active)
gst_pad_set_caps (pad, NULL);
/* unref the object that was reffed for us by _fold */
gst_object_unref (pad);
- return TRUE;
+ return cont;
}
-/* returns false on error or early cutout (will never happen because the fold
- * function always returns TRUE, see FIXME above) of the fold, true if all
+/* returns false on error or early cutout of the fold, true if all
* pads in @iter were (de)activated successfully. */
static gboolean
iterator_activate_fold_with_resync (GstIterator * iter, gpointer user_data)
return res;
}
+static void
+gst_bin_state_changed (GstElement * element, GstState oldstate,
+ GstState newstate, GstState pending)
+{
+ GstElementClass *pklass = (GstElementClass *) parent_class;
+
+ if (newstate == GST_STATE_PLAYING && pending == GST_STATE_VOID_PENDING)
+ bin_do_eos (GST_BIN_CAST (element));
+
+ if (pklass->state_changed)
+ pklass->state_changed (element, oldstate, newstate, pending);
+}
+
static GstStateChangeReturn
gst_bin_change_state_func (GstElement * element, GstStateChange transition)
{
GST_OBJECT_LOCK (bin);
GST_DEBUG_OBJECT (element, "clearing EOS elements");
bin_remove_messages (bin, NULL, GST_MESSAGE_EOS);
+ bin->priv->posted_eos = FALSE;
GST_OBJECT_UNLOCK (bin);
if (current == GST_STATE_READY)
if (!(gst_bin_src_pads_activate (bin, TRUE)))
GST_STATE_UNLOCK (bin);
GST_DEBUG_OBJECT (bin, "state continue done");
+
gst_object_unref (bin);
g_slice_free (BinContinueData, data);
return;
GST_OBJECT_UNLOCK (bin);
/* post message */
- gst_element_post_message (GST_ELEMENT_CAST (bin),
- gst_message_new_state_changed (GST_OBJECT_CAST (bin),
- new_state, new_state, new_state));
+ _priv_gst_element_state_changed (GST_ELEMENT_CAST (bin), new_state, new_state,
+ new_state);
post_start:
if (amessage) {
GstState current, pending, target;
GstStateChangeReturn old_ret;
GstState old_state, old_next;
- gboolean toplevel;
- GstMessage *smessage = NULL, *amessage = NULL;
+ gboolean toplevel, state_changed = FALSE;
+ GstMessage *amessage = NULL;
BinContinueData *cont = NULL;
if (GST_STATE_RETURN (bin) == GST_STATE_CHANGE_FAILURE)
if (old_next != GST_STATE_PLAYING) {
if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
- smessage = gst_message_new_state_changed (GST_OBJECT_CAST (bin),
- old_state, old_next, pending);
+ state_changed = TRUE;
}
}
GST_OBJECT_UNLOCK (bin);
- if (smessage) {
- GST_DEBUG_OBJECT (bin, "posting state change message");
- gst_element_post_message (GST_ELEMENT_CAST (bin), smessage);
+ if (state_changed) {
+ _priv_gst_element_state_changed (GST_ELEMENT_CAST (bin), old_state,
+ old_next, pending);
}
if (amessage) {
/* post our combined ASYNC_DONE when all is ASYNC_DONE. */
}
}
+static void
+bin_do_eos (GstBin * bin)
+{
+ guint32 seqnum = 0;
+ gboolean eos;
+
+ GST_OBJECT_LOCK (bin);
+ /* If all sinks are EOS, we're in PLAYING and no state change is pending
+ * we forward the EOS message to the parent bin or application
+ */
+ eos = GST_STATE (bin) == GST_STATE_PLAYING
+ && GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING
+ && is_eos (bin, &seqnum);
+ GST_OBJECT_UNLOCK (bin);
+
+ if (eos
+ && g_atomic_int_compare_and_exchange (&bin->priv->posted_eos, FALSE,
+ TRUE)) {
+ GstMessage *tmessage;
+ tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin));
+ gst_message_set_seqnum (tmessage, seqnum);
+ GST_DEBUG_OBJECT (bin,
+ "all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum);
+ gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
+ }
+}
+
/* must be called with the object lock. This function releases the lock to post
* the message. */
static void
}
case GST_MESSAGE_EOS:
{
- gboolean eos;
/* collect all eos messages from the children */
GST_OBJECT_LOCK (bin);
bin_do_message_forward (bin, message);
/* ref message for future use */
- gst_message_ref (message);
bin_replace_message (bin, message, GST_MESSAGE_EOS);
- eos = is_eos (bin);
GST_OBJECT_UNLOCK (bin);
- /* if we are completely EOS, we forward an EOS message */
- if (eos) {
- seqnum = gst_message_get_seqnum (message);
- tmessage = gst_message_new_eos (GST_OBJECT_CAST (bin));
- gst_message_set_seqnum (tmessage, seqnum);
-
- GST_DEBUG_OBJECT (bin,
- "all sinks posted EOS, posting seqnum #%" G_GUINT32_FORMAT, seqnum);
- gst_element_post_message (GST_ELEMENT_CAST (bin), tmessage);
- }
- gst_message_unref (message);
+ bin_do_eos (bin);
break;
}
case GST_MESSAGE_STATE_DIRTY:
diff --git a/gst/gstcaps.c b/gst/gstcaps.c
index 5d8912c4d365ebdcb487692de5d6c8a51a1e578c..6cc673132d6a63e8007a0e88670f1328566c0e4d 100644 (file)
--- a/gst/gstcaps.c
+++ b/gst/gstcaps.c
return gst_caps_remove_and_get_structure (caps, index);
}
-static gboolean
-gst_structure_is_equal_foreach (GQuark field_id, const GValue * val2,
- gpointer data)
-{
- GstStructure *struct1 = (GstStructure *) data;
- const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
-
- if (G_UNLIKELY (val1 == NULL))
- return FALSE;
- if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value,
- gpointer user_data)
-{
- GstStructure *subtract_from = user_data;
- GValue subtraction = { 0, };
- const GValue *other;
-
- if (!(other = gst_structure_id_get_value (subtract_from, field_id)))
- /* field is missing in one set */
- return FALSE;
-
- /* equal values are subset */
- if (gst_value_compare (other, value) == GST_VALUE_EQUAL)
- return TRUE;
-
- /*
- * 1 - [1,2] = empty
- * -> !subset
- *
- * [1,2] - 1 = 2
- * -> 1 - [1,2] = empty
- * -> subset
- *
- * [1,3] - [1,2] = 3
- * -> [1,2] - [1,3] = empty
- * -> subset
- *
- * {1,2} - {1,3} = 2
- * -> {1,3} - {1,2} = 3
- * -> !subset
- *
- * First caps subtraction needs to return a non-empty set, second
- * subtractions needs to give en empty set.
- */
- if (gst_value_subtract (&subtraction, other, value)) {
- g_value_unset (&subtraction);
- /* !empty result, swapping must be empty */
- if (!gst_value_subtract (&subtraction, value, other))
- return TRUE;
-
- g_value_unset (&subtraction);
- }
- return FALSE;
-}
-
-static gboolean
-gst_caps_structure_is_subset (const GstStructure * minuend,
- const GstStructure * subtrahend)
-{
- if ((minuend->name != subtrahend->name) ||
- (gst_structure_n_fields (minuend) !=
- gst_structure_n_fields (subtrahend))) {
- return FALSE;
- }
-
- return gst_structure_foreach ((GstStructure *) subtrahend,
- gst_caps_structure_is_subset_field, (gpointer) minuend);
-}
-
/**
* gst_caps_append:
* @caps1: the #GstCaps that will be appended to
for (i = caps->structs->len - 1; i >= 0; i--) {
structure1 = gst_caps_get_structure_unchecked (caps, i);
/* if structure is a subset of structure1, then skip it */
- if (gst_caps_structure_is_subset (structure1, structure)) {
+ if (gst_structure_is_subset (structure, structure1)) {
unique = FALSE;
break;
}
@@ -982,12 +906,7 @@ gst_caps_set_simple_valist (GstCaps * caps, const char *field, va_list varargs)
g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
type = GST_TYPE_DATE;
}
-#if GLIB_CHECK_VERSION(2,23,3)
G_VALUE_COLLECT_INIT (&value, type, varargs, 0, &err);
-#else
- g_value_init (&value, type);
- G_VALUE_COLLECT (&value, varargs, 0, &err);
-#endif
if (G_UNLIKELY (err)) {
g_critical ("%s", err);
return;
struct1 = gst_caps_get_structure_unchecked (caps1, 0);
struct2 = gst_caps_get_structure_unchecked (caps2, 0);
- if (struct1->name != struct2->name) {
- return FALSE;
- }
- if (struct1->fields->len != struct2->fields->len) {
- return FALSE;
- }
-
- return gst_structure_foreach (struct1, gst_structure_is_equal_foreach,
- struct2);
+ return gst_structure_is_equal (struct1, struct2);
}
/**
gboolean
gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
{
- GstCaps *caps;
- gboolean ret;
+ GstStructure *s1, *s2;
+ gboolean ret = TRUE;
+ gint i, j;
g_return_val_if_fail (subset != NULL, FALSE);
g_return_val_if_fail (superset != NULL, FALSE);
if (CAPS_IS_ANY (subset) || CAPS_IS_EMPTY (superset))
return FALSE;
- caps = gst_caps_subtract (subset, superset);
- ret = CAPS_IS_EMPTY_SIMPLE (caps);
- gst_caps_unref (caps);
+ for (i = subset->structs->len - 1; i >= 0; i--) {
+ for (j = superset->structs->len - 1; j >= 0; j--) {
+ s1 = gst_caps_get_structure_unchecked (subset, i);
+ s2 = gst_caps_get_structure_unchecked (superset, j);
+ if (gst_structure_is_subset (s1, s2)) {
+ /* If we found a superset, continue with the next
+ * subset structure */
+ break;
+ }
+ }
+ /* If we found no superset for this subset structure
+ * we return FALSE immediately */
+ if (j == -1) {
+ ret = FALSE;
+ break;
+ }
+ }
+
return ret;
}
+/**
+ * gst_caps_is_subset_structure:
+ * @caps: a #GstCaps
+ * @structure: a potential #GstStructure subset of @caps
+ *
+ * Checks if @structure is a subset of @caps. See gst_caps_is_subset()
+ * for more information.
+ *
+ * Returns: %TRUE if @structure is a subset of @caps
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_caps_is_subset_structure (const GstCaps * caps,
+ const GstStructure * structure)
+{
+ GstStructure *s;
+ gint i;
+
+ g_return_val_if_fail (caps != NULL, FALSE);
+ g_return_val_if_fail (structure != NULL, FALSE);
+
+ if (CAPS_IS_ANY (caps))
+ return TRUE;
+ if (CAPS_IS_EMPTY (caps))
+ return FALSE;
+
+ for (i = caps->structs->len - 1; i >= 0; i--) {
+ s = gst_caps_get_structure_unchecked (caps, i);
+ if (gst_structure_is_subset (structure, s)) {
+ /* If we found a superset return TRUE */
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/**
* gst_caps_is_equal:
* @caps1: a #GstCaps
/* intersect operation */
-typedef struct
-{
- GstStructure *dest;
- const GstStructure *intersect;
-}
-IntersectData;
-
-static gboolean
-gst_caps_structure_intersect_field1 (GQuark id, const GValue * val1,
- gpointer data)
-{
- IntersectData *idata = (IntersectData *) data;
- const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
-
- if (G_UNLIKELY (val2 == NULL)) {
- gst_structure_id_set_value (idata->dest, id, val1);
- } else {
- GValue dest_value = { 0 };
- if (gst_value_intersect (&dest_value, val1, val2)) {
- gst_structure_id_set_value (idata->dest, id, &dest_value);
- g_value_unset (&dest_value);
- } else {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-static gboolean
-gst_caps_structure_intersect_field2 (GQuark id, const GValue * val1,
- gpointer data)
-{
- IntersectData *idata = (IntersectData *) data;
- const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
-
- if (G_UNLIKELY (val2 == NULL)) {
- gst_structure_id_set_value (idata->dest, id, val1);
- }
- return TRUE;
-}
-
-static GstStructure *
-gst_caps_structure_intersect (const GstStructure * struct1,
- const GstStructure * struct2)
-{
- IntersectData data;
-
- g_assert (struct1 != NULL);
- g_assert (struct2 != NULL);
-
- if (G_UNLIKELY (struct1->name != struct2->name))
- return NULL;
-
- /* copy fields from struct1 which we have not in struct2 to target
- * intersect if we have the field in both */
- data.dest = gst_structure_id_empty_new (struct1->name);
- data.intersect = struct2;
- if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
- gst_caps_structure_intersect_field1, &data)))
- goto error;
-
- /* copy fields from struct2 which we have not in struct1 to target */
- data.intersect = struct1;
- if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2,
- gst_caps_structure_intersect_field2, &data)))
- goto error;
-
- return data.dest;
-
-error:
- gst_structure_free (data.dest);
- return NULL;
-}
-
-static gboolean
-gst_caps_structure_can_intersect_field (GQuark id, const GValue * val1,
- gpointer data)
-{
- GstStructure *other = (GstStructure *) data;
- const GValue *val2 = gst_structure_id_get_value (other, id);
-
- if (G_LIKELY (val2)) {
- if (!gst_value_can_intersect (val1, val2)) {
- return FALSE;
- } else {
- gint eq = gst_value_compare (val1, val2);
-
- if (eq == GST_VALUE_UNORDERED) {
- /* we need to try interseting */
- GValue dest_value = { 0 };
- if (gst_value_intersect (&dest_value, val1, val2)) {
- g_value_unset (&dest_value);
- } else {
- return FALSE;
- }
- } else if (eq != GST_VALUE_EQUAL) {
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-static gboolean
-gst_caps_structure_can_intersect (const GstStructure * struct1,
- const GstStructure * struct2)
-{
- g_assert (struct1 != NULL);
- g_assert (struct2 != NULL);
-
- if (G_UNLIKELY (struct1->name != struct2->name))
- return FALSE;
-
- /* tries to intersect if we have the field in both */
- if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
- gst_caps_structure_can_intersect_field, (gpointer) struct2)))
- return FALSE;
-
- return TRUE;
-}
-
/**
* gst_caps_can_intersect:
* @caps1: a #GstCaps to intersect
struct1 = gst_caps_get_structure_unchecked (caps1, j);
struct2 = gst_caps_get_structure_unchecked (caps2, k);
- if (gst_caps_structure_can_intersect (struct1, struct2)) {
+ if (gst_structure_can_intersect (struct1, struct2)) {
return TRUE;
}
/* move down left */
struct1 = gst_caps_get_structure_unchecked (caps1, j);
struct2 = gst_caps_get_structure_unchecked (caps2, k);
- istruct = gst_caps_structure_intersect (struct1, struct2);
+ istruct = gst_structure_intersect (struct1, struct2);
- gst_caps_append_structure (dest, istruct);
+ gst_caps_merge_structure (dest, istruct);
/* move down left */
k++;
if (G_UNLIKELY (j == 0))
struct1 = gst_caps_get_structure_unchecked (caps1, i);
for (j = 0; j < len2; j++) {
struct2 = gst_caps_get_structure_unchecked (caps2, j);
- istruct = gst_caps_structure_intersect (struct1, struct2);
+ istruct = gst_structure_intersect (struct1, struct2);
if (istruct)
- gst_caps_append_structure (dest, istruct);
+ gst_caps_merge_structure (dest, istruct);
}
}
diff --git a/gst/gstcaps.h b/gst/gstcaps.h
index f79939c61af80057c3d8914c9f9b37f440ed2310..b7c5c0fc3a8f2bbe967b3ef004f4826085af0036 100644 (file)
--- a/gst/gstcaps.h
+++ b/gst/gstcaps.h
const GstCaps *caps2);
gboolean gst_caps_is_subset (const GstCaps *subset,
const GstCaps *superset);
+gboolean gst_caps_is_subset_structure (const GstCaps *caps,
+ const GstStructure *structure);
gboolean gst_caps_is_equal (const GstCaps *caps1,
const GstCaps *caps2);
gboolean gst_caps_is_equal_fixed (const GstCaps *caps1,
diff --git a/gst/gstchildproxy.c b/gst/gstchildproxy.c
index 65e9527a4d01b1d4cf4d1c8245ca7845f09b9778..2054aa0298254cad2666194cbd16e71fdc54e3bc 100644 (file)
--- a/gst/gstchildproxy.c
+++ b/gst/gstchildproxy.c
if (!gst_child_proxy_lookup (object, name, &target, &pspec))
goto not_found;
-#if GLIB_CHECK_VERSION(2,23,3)
G_VALUE_COLLECT_INIT (&value, pspec->value_type, var_args,
G_VALUE_NOCOPY_CONTENTS, &error);
-#else
- g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
- G_VALUE_COLLECT (&value, var_args, G_VALUE_NOCOPY_CONTENTS, &error);
-#endif
+
if (error)
goto cant_copy;
diff --git a/gst/gstclock.h b/gst/gstclock.h
index cc1ed0940b6ebb8a3eac98fda1f4a81a26fd234a..230e19058828908d39efde70be1a6c6b2d146a46 100644 (file)
--- a/gst/gstclock.h
+++ b/gst/gstclock.h
/**
* GST_TIME_FORMAT:
*
- * A format that can be used in printf like format strings to format
- * a #GstClockTime value.
+ * A string that can be used in printf-like format strings to display a
+ * #GstClockTime value in h:m:s format. Use GST_TIME_ARGS() to construct
+ * the matching arguments.
+ *
+ * Example:
+ * |[
+ * printf("%" GST_TIME_FORMAT "\n", GST_TIME_ARGS(ts));
+ * ]|
*/
#define GST_TIME_FORMAT "u:%02u:%02u.%09u"
/**
* GST_TIME_ARGS:
* @t: a #GstClockTime
*
- * Format @t for the GST_TIME_FORMAT format string.
+ * Format @t for the #GST_TIME_FORMAT format string. Note: @t will be
+ * evaluated more than once.
*/
#define GST_TIME_ARGS(t) \
GST_CLOCK_TIME_IS_VALID (t) ? \
* @tv: a #GTimeVal to wait.
*
* Wait on the clock until the entries changed or the specified timeout
- * occurred.
+ * occurred.
*/
#define GST_CLOCK_TIMED_WAIT(clock,tv) g_cond_timed_wait(GST_CLOCK_COND(clock),GST_OBJECT_GET_LOCK(clock),tv)
/**
GMutex *slave_lock; /* order: SLAVE_LOCK, OBJECT_LOCK */
/*< protected >*/ /* with LOCK */
- GstClockTime internal_calibration;
+ GstClockTime internal_calibration;
GstClockTime external_calibration;
GstClockTime rate_numerator;
GstClockTime rate_denominator;
/* master/slave clocks */
gboolean gst_clock_set_master (GstClock *clock, GstClock *master);
GstClock* gst_clock_get_master (GstClock *clock);
-gboolean gst_clock_add_observation (GstClock *clock, GstClockTime slave,
+gboolean gst_clock_add_observation (GstClock *clock, GstClockTime slave,
GstClockTime master, gdouble *r_squared);
diff --git a/gst/gstelement.c b/gst/gstelement.c
index 12fc6fac8a078b3b07fe3b2976ebb00fa09d98ed..ddbba3e409b4008512494992a7d8e00bd09fc1bd 100644 (file)
--- a/gst/gstelement.c
+++ b/gst/gstelement.c
}
}
+/* Not static because GstBin has manual state handling too */
+void
+_priv_gst_element_state_changed (GstElement * element, GstState oldstate,
+ GstState newstate, GstState pending)
+{
+ GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
+ GstMessage *message;
+
+ GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
+ "notifying about state-changed %s to %s (%s pending)",
+ gst_element_state_get_name (oldstate),
+ gst_element_state_get_name (newstate),
+ gst_element_state_get_name (pending));
+
+ if (klass->state_changed)
+ klass->state_changed (element, oldstate, newstate, pending);
+
+ message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
+ oldstate, newstate, pending);
+ gst_element_post_message (element, message);
+}
+
/**
* gst_element_continue_state:
* @element: a #GstElement to continue the state change of.
GstStateChangeReturn old_ret;
GstState old_state, old_next;
GstState current, next, pending;
- GstMessage *message;
GstStateChange transition;
GST_OBJECT_LOCK (element);
gst_element_state_get_name (old_next),
gst_element_state_get_name (pending), gst_element_state_get_name (next));
- message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
- old_state, old_next, pending);
- gst_element_post_message (element, message);
+ _priv_gst_element_state_changed (element, old_state, old_next, pending);
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
"continue state change %s to %s, final %s",
* previous return value.
* We do signal the cond though as a _get_state() might be blocking
* on it. */
- if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC) {
- GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
- "posting state-changed %s to %s",
- gst_element_state_get_name (old_state),
- gst_element_state_get_name (old_next));
- message =
- gst_message_new_state_changed (GST_OBJECT_CAST (element), old_state,
- old_next, GST_STATE_VOID_PENDING);
- gst_element_post_message (element, message);
- }
+ if (old_state != old_next || old_ret == GST_STATE_CHANGE_ASYNC)
+ _priv_gst_element_state_changed (element, old_state, old_next,
+ GST_STATE_VOID_PENDING);
GST_STATE_BROADCAST (element);
GST_ELEMENT_START_TIME (element) = 0;
GST_OBJECT_UNLOCK (element);
- message = gst_message_new_state_changed (GST_OBJECT_CAST (element),
- new_state, new_state, new_state);
- gst_element_post_message (element, message);
+ _priv_gst_element_state_changed (element, new_state, new_state, new_state);
message =
gst_message_new_async_start (GST_OBJECT_CAST (element), new_base_time);
}
/* gst_iterator_fold functions for pads_activate
- * Note how we don't stop the iterator when we fail an activation. This is
- * probably a FIXME since when one pad activation fails, we don't want to
- * continue our state change. */
+ * Stop the iterator if activating one pad failed. */
static gboolean
activate_pads (GstPad * pad, GValue * ret, gboolean * active)
{
- if (!gst_pad_set_active (pad, *active))
+ gboolean cont = TRUE;
+
+ if (!(cont = gst_pad_set_active (pad, *active)))
g_value_set_boolean (ret, FALSE);
/* unref the object that was reffed for us by _fold */
gst_object_unref (pad);
- return TRUE;
+ return cont;
}
/* set the caps on the pad to NULL */
return TRUE;
}
-/* returns false on error or early cutout (will never happen because the fold
- * function always returns TRUE, see FIXME above) of the fold, true if all
+/* returns false on error or early cutout of the fold, true if all
* pads in @iter were (de)activated successfully. */
static gboolean
iterator_activate_fold_with_resync (GstIterator * iter,
diff --git a/gst/gstelement.h b/gst/gstelement.h
index 04b5ba820cef8e872940a5275004e80dd441c8fd..74a0e2ce9b628c1753dee94e1fcf6c6e1d0f0cb2 100644 (file)
--- a/gst/gstelement.h
+++ b/gst/gstelement.h
* cannot produce data in %GST_STATE_PAUSED.
* This typically happens with live sources.
*
- * The possible return values from a state change function. Only
- * @GST_STATE_CHANGE_FAILURE is a real failure.
+ * The possible return values from a state change function such as
+ * gst_element_set_state(). Only @GST_STATE_CHANGE_FAILURE is a real failure.
*/
typedef enum {
GST_STATE_CHANGE_FAILURE = 0,
* Streaming threads are started.
* </para></listitem>
* <listitem><para>
- * Some elements might need to return ASYNC and complete the state change
- * when they have enough information. It is a requirement for sinks to
- * return ASYNC and complete the state change when they receive the first
- * buffer or EOS event (preroll). Sinks also block the dataflow when in
- * PAUSED.
+ * Some elements might need to return %GST_STATE_CHANGE_ASYNC and complete
+ * the state change when they have enough information. It is a requirement
+ * for sinks to return %GST_STATE_CHANGE_ASYNC and complete the state change
+ * when they receive the first buffer or %GST_EVENT_EOS (preroll).
+ * Sinks also block the dataflow when in PAUSED.
* </para></listitem>
* <listitem><para>
* A pipeline resets the running_time to 0.
* </para></listitem>
* <listitem><para>
- * Live sources return NO_PREROLL and don't generate data.
+ * Live sources return %GST_STATE_CHANGE_NO_PREROLL and don't generate data.
* </para></listitem>
* </itemizedlist>
* @GST_STATE_CHANGE_PAUSED_TO_PLAYING: state change from PAUSED to PLAYING.
* Most elements ignore this state change.
* </para></listitem>
* <listitem><para>
- * The pipeline selects a clock and distributes this to all the children
+ * The pipeline selects a #GstClock and distributes this to all the children
* before setting them to PLAYING. This means that it is only alowed to
- * synchronize on the clock in the PLAYING state.
+ * synchronize on the #GstClock in the PLAYING state.
* </para></listitem>
* <listitem><para>
- * The pipeline uses the clock and the running_time to calculate the
+ * The pipeline uses the #GstClock and the running_time to calculate the
* base_time. The base_time is distributed to all children when performing
* the state change.
* </para></listitem>
* rendering the data.
* </para></listitem>
* <listitem><para>
- * Sinks can post the EOS message in the PLAYING state. It is not allowed to
- * post EOS when not in the PLAYING state.
+ * Sinks can post %GST_MESSAGE_EOS in the PLAYING state. It is not allowed
+ * to post %GST_MESSAGE_EOS when not in the PLAYING state.
* </para></listitem>
* <listitem><para>
* While streaming in PAUSED or PLAYING elements can create and remove
* sometimes pads.
* </para></listitem>
* <listitem><para>
- * Live sources start generating data and return SUCCESS.
+ * Live sources start generating data and return %GST_STATE_CHANGE_SUCCESS.
* </para></listitem>
* </itemizedlist>
* @GST_STATE_CHANGE_PLAYING_TO_PAUSED: state change from PLAYING to PAUSED.
* Most elements ignore this state change.
* </para></listitem>
* <listitem><para>
- * The pipeline calculates the running_time based on the last selected clock
- * and the base_time. It stores this information to continue playback when
- * going back to the PLAYING state.
+ * The pipeline calculates the running_time based on the last selected
+ * #GstClock and the base_time. It stores this information to continue
+ * playback when going back to the PLAYING state.
* </para></listitem>
* <listitem><para>
- * Sinks unblock any clock wait calls.
+ * Sinks unblock any #GstClock wait calls.
* </para></listitem>
* <listitem><para>
- * When a sink does not have a pending buffer to play, it returns ASYNC from
- * this state change and completes the state change when it receives a new
- * buffer or an EOS event.
+ * When a sink does not have a pending buffer to play, it returns
+ * %GST_STATE_CHANGE_ASYNC from this state change and completes the state
+ * change when it receives a new buffer or an %GST_EVENT_EOS.
* </para></listitem>
* <listitem><para>
- * Any queued EOS messages are removed since they will be reposted when going
- * back to the PLAYING state. The EOS messages are queued in GstBins.
+ * Any queued %GST_MESSAGE_EOS items are removed since they will be reposted
+ * when going back to the PLAYING state. The EOS messages are queued in
+ * #GstBin containers.
* </para></listitem>
* <listitem><para>
- * Live sources stop generating data and return NO_PREROLL.
+ * Live sources stop generating data and return %GST_STATE_CHANGE_NO_PREROLL.
* </para></listitem>
* </itemizedlist>
* @GST_STATE_CHANGE_PAUSED_TO_READY : state change from PAUSED to READY.
* Elements unblock any waits on devices
* </para></listitem>
* <listitem><para>
- * Chain or get_range functions return WRONG_STATE.
+ * Chain or get_range functions return %GST_FLOW_WRONG_STATE.
* </para></listitem>
* <listitem><para>
* The element pads are deactivated so that streaming becomes impossible and
* @get_query_types: get the supported #GstQueryType of this element
* @query: perform a #GstQuery on the element
* @request_new_pad_full: called when a new pad is requested. Since: 0.10.32.
+ * @state_changed: called immediately after a new state was set. Since: 0.10.35.
*
* GStreamer element class. Override the vmethods to implement the element
* functionality.
GstPad* (*request_new_pad_full) (GstElement *element, GstPadTemplate *templ,
const gchar* name, const GstCaps *caps);
+ void (*state_changed) (GstElement *element, GstState oldstate,
+ GstState newstate, GstState pending);
+
/*< private >*/
- gpointer _gst_reserved[GST_PADDING-2];
+ gpointer _gst_reserved[GST_PADDING-3];
};
/* element class pad templates */
diff --git a/gst/gstghostpad.c b/gst/gstghostpad.c
index 313759d5a4f0432c688775415b9cadeccba2bee8..4a024a26efb952edd1a42b9c475f90e240c29255 100644 (file)
--- a/gst/gstghostpad.c
+++ b/gst/gstghostpad.c
G_DEFINE_TYPE (GstProxyPad, gst_proxy_pad, GST_TYPE_PAD);
static GstPad *gst_proxy_pad_get_target (GstPad * pad);
-static GstPad *gst_proxy_pad_get_internal (GstPad * pad);
static void gst_proxy_pad_dispose (GObject * object);
static void gst_proxy_pad_finalize (GObject * object);
static GParamSpec *pspec_caps = NULL;
-static const GstQueryType *
-gst_proxy_pad_do_query_type (GstPad * pad)
+/**
+ * gst_proxy_pad_query_type_default:
+ * @pad: a #GstPad.
+ *
+ * Invoke the default query type handler of the proxy pad.
+ *
+ * Returns: (transfer none) (array zero-terminated=1): a zero-terminated array
+ * of #GstQueryType.
+ *
+ * Since: 0.10.35
+ */
+const GstQueryType *
+gst_proxy_pad_query_type_default (GstPad * pad)
{
- GstPad *target = gst_proxy_pad_get_target (pad);
+ GstPad *target;
const GstQueryType *res = NULL;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
+
+ target = gst_proxy_pad_get_target (pad);
if (target) {
res = gst_pad_get_query_types (target);
gst_object_unref (target);
return res;
}
-static gboolean
-gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
+/**
+ * gst_proxy_pad_event_default:
+ * @pad: a #GstPad to push the event to.
+ * @event: (transfer full): the #GstEvent to send to the pad.
+ *
+ * Invoke the default event of the proxy pad.
+ *
+ * Returns: TRUE if the event was handled.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_proxy_pad_event_default (GstPad * pad, GstEvent * event)
{
gboolean res = FALSE;
- GstPad *internal = gst_proxy_pad_get_internal (pad);
+ GstPad *internal;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+ g_return_val_if_fail (GST_IS_EVENT (event), FALSE);
+
+ internal =
+ GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
if (internal) {
res = gst_pad_push_event (internal, event);
gst_object_unref (internal);
return res;
}
-static gboolean
-gst_proxy_pad_do_query (GstPad * pad, GstQuery * query)
+/**
+ * gst_proxy_pad_query_default:
+ * @pad: a #GstPad to invoke the default query on.
+ * @query: (transfer none): the #GstQuery to perform.
+ *
+ * Invoke the default query function of the proxy pad.
+ *
+ * Returns: TRUE if the query could be performed.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_proxy_pad_query_default (GstPad * pad, GstQuery * query)
{
gboolean res = FALSE;
- GstPad *target = gst_proxy_pad_get_target (pad);
+ GstPad *target;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+ g_return_val_if_fail (GST_IS_QUERY (query), FALSE);
+
+ target = gst_proxy_pad_get_target (pad);
if (target) {
res = gst_pad_query (target, query);
gst_object_unref (target);
return res;
}
-static GstIterator *
-gst_proxy_pad_do_iterate_internal_links (GstPad * pad)
+/**
+ * gst_proyx_pad_iterate_internal_links_default:
+ * @pad: the #GstPad to get the internal links of.
+ *
+ * Invoke the default iterate internal links function of the proxy pad.
+ *
+ * Returns: a #GstIterator of #GstPad, or NULL if @pad has no parent. Unref each
+ * returned pad with gst_object_unref().
+ *
+ * Since: 0.10.35
+ */
+GstIterator *
+gst_proxy_pad_iterate_internal_links_default (GstPad * pad)
{
GstIterator *res = NULL;
- GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
+ GstPad *internal;
+
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
+
+ internal =
+ GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
if (internal) {
res =
gst_iterator_new_single (GST_TYPE_PAD, internal,
(GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
+ gst_object_unref (internal);
}
return res;
}
-static GstFlowReturn
-gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
+/**
+ * gst_proxy_pad_bufferalloc_default:
+ * @pad: a source #GstPad
+ * @offset: the offset of the new buffer in the stream
+ * @size: the size of the new buffer
+ * @caps: the caps of the new buffer
+ * @buf: a newly allocated buffer
+ *
+ * Invoke the default bufferalloc function of the proxy pad.
+ *
+ * Returns: a result code indicating success of the operation. Any
+ * result code other than #GST_FLOW_OK is an error and @buf should
+ * not be used.
+ * An error can occur if the pad is not connected or when the downstream
+ * peer elements cannot provide an acceptable buffer.
+ *
+ * Since: 0.10.35
+ */
+GstFlowReturn
+gst_proxy_pad_bufferalloc_default (GstPad * pad, guint64 offset, guint size,
GstCaps * caps, GstBuffer ** buf)
{
GstFlowReturn result = GST_FLOW_WRONG_STATE;
- GstPad *internal = gst_proxy_pad_get_internal (pad);
+ GstPad *internal;
+
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), GST_FLOW_ERROR);
+ g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
+ internal =
+ GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD_CAST (pad)));
if (internal) {
result = gst_pad_alloc_buffer (internal, offset, size, caps, buf);
gst_object_unref (internal);
return result;
}
-static GstFlowReturn
-gst_proxy_pad_do_chain (GstPad * pad, GstBuffer * buffer)
+/**
+ * gst_proxy_pad_chain_default:
+ * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
+ * @buffer: (transfer full): the #GstBuffer to send, return GST_FLOW_ERROR
+ * if not.
+ *
+ * Invoke the default chain function of the proxy pad.
+ *
+ * Returns: a #GstFlowReturn from the pad.
+ *
+ * Since: 0.10.35
+ */
+GstFlowReturn
+gst_proxy_pad_chain_default (GstPad * pad, GstBuffer * buffer)
{
GstFlowReturn res;
- GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
+ GstPad *internal;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR);
+
+ internal = GST_PROXY_PAD_INTERNAL (pad);
res = gst_pad_push (internal, buffer);
return res;
}
-static GstFlowReturn
-gst_proxy_pad_do_chain_list (GstPad * pad, GstBufferList * list)
+/**
+ * gst_proxy_pad_chain_list_default:
+ * @pad: a sink #GstPad, returns GST_FLOW_ERROR if not.
+ * @list: (transfer full): the #GstBufferList to send, return GST_FLOW_ERROR
+ * if not.
+ *
+ * Invoke the default chain list function of the proxy pad.
+ *
+ * Returns: a #GstFlowReturn from the pad.
+ *
+ * Since: 0.10.35
+ */
+GstFlowReturn
+gst_proxy_pad_chain_list_default (GstPad * pad, GstBufferList * list)
{
GstFlowReturn res;
- GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
+ GstPad *internal;
+
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (GST_IS_BUFFER_LIST (list), GST_FLOW_ERROR);
+ internal = GST_PROXY_PAD_INTERNAL (pad);
res = gst_pad_push_list (internal, list);
return res;
}
-static GstFlowReturn
-gst_proxy_pad_do_getrange (GstPad * pad, guint64 offset, guint size,
+/**
+ * gst_proxy_pad_get_range_default:
+ * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
+ * @offset: The start offset of the buffer
+ * @size: The length of the buffer
+ * @buffer: (out callee-allocates): a pointer to hold the #GstBuffer,
+ * returns #GST_FLOW_ERROR if %NULL.
+ *
+ * Invoke the default getrange function of the proxy pad.
+ *
+ * Returns: a #GstFlowReturn from the pad.
+ *
+ * Since: 0.10.35
+ */
+GstFlowReturn
+gst_proxy_pad_getrange_default (GstPad * pad, guint64 offset, guint size,
GstBuffer ** buffer)
{
GstFlowReturn res;
- GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
+ GstPad *internal;
+
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), GST_FLOW_ERROR);
+ g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
+ internal = GST_PROXY_PAD_INTERNAL (pad);
res = gst_pad_pull_range (internal, offset, size, buffer);
return res;
}
-static gboolean
-gst_proxy_pad_do_checkgetrange (GstPad * pad)
+/**
+ * gst_proxy_pad_checkgetrange_default:
+ * @pad: a src #GstPad, returns #GST_FLOW_ERROR if not.
+ *
+ * Invoke the default checkgetrange function of the proxy pad.
+ *
+ * Returns: a #gboolean from the pad.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_proxy_pad_checkgetrange_default (GstPad * pad)
{
gboolean result;
- GstPad *internal = GST_PROXY_PAD_INTERNAL (pad);
+ GstPad *internal;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+
+ internal = GST_PROXY_PAD_INTERNAL (pad);
result = gst_pad_check_pull_range (internal);
return result;
}
-static GstCaps *
-gst_proxy_pad_do_getcaps (GstPad * pad)
+/**
+ * gst_proxy_pad_getcaps_default:
+ * @pad: a #GstPad to get the capabilities of.
+ *
+ * Invoke the default getcaps function of the proxy pad.
+ *
+ * Returns: (transfer full): the caps of the pad with incremented ref-count
+ *
+ * Since: 0.10.35
+ */
+GstCaps *
+gst_proxy_pad_getcaps_default (GstPad * pad)
{
- GstPad *target = gst_proxy_pad_get_target (pad);
+ GstPad *target;
GstCaps *res;
- GstPadTemplate *templ = GST_PAD_PAD_TEMPLATE (pad);
+ GstPadTemplate *templ;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
+
+ templ = GST_PAD_PAD_TEMPLATE (pad);
+ target = gst_proxy_pad_get_target (pad);
if (target) {
/* if we have a real target, proxy the call */
res = gst_pad_get_caps_reffed (target);
return res;
}
-static gboolean
-gst_proxy_pad_do_acceptcaps (GstPad * pad, GstCaps * caps)
+/**
+ * gst_proxy_pad_acceptcaps_default:
+ * @pad: a #GstPad to check
+ * @caps: a #GstCaps to check on the pad
+ *
+ * Invoke the default acceptcaps function of the proxy pad.
+ *
+ * Returns: TRUE if the pad can accept the caps.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_proxy_pad_acceptcaps_default (GstPad * pad, GstCaps * caps)
{
- GstPad *target = gst_proxy_pad_get_target (pad);
+ GstPad *target;
gboolean res;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+ g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
+
+ target = gst_proxy_pad_get_target (pad);
if (target) {
res = gst_pad_accept_caps (target, caps);
gst_object_unref (target);
return res;
}
-static void
-gst_proxy_pad_do_fixatecaps (GstPad * pad, GstCaps * caps)
+/**
+ * gst_proxy_pad_fixatecaps_default:
+ * @pad: a #GstPad to fixate
+ * @caps: the #GstCaps to fixate
+ *
+ * Invoke the default fixatecaps function of the proxy pad.
+ *
+ * Since: 0.10.35
+ */
+void
+gst_proxy_pad_fixatecaps_default (GstPad * pad, GstCaps * caps)
{
- GstPad *target = gst_proxy_pad_get_target (pad);
+ GstPad *target;
+
+ g_return_if_fail (GST_IS_PROXY_PAD (pad));
+ g_return_if_fail (GST_IS_CAPS (caps));
+ target = gst_proxy_pad_get_target (pad);
if (target) {
gst_pad_fixate_caps (target, caps);
gst_object_unref (target);
}
}
-static gboolean
-gst_proxy_pad_do_setcaps (GstPad * pad, GstCaps * caps)
+/**
+ * gst_proxy_pad_setcaps_default:
+ * @pad: a #GstPad to set the capabilities of.
+ * @caps: (transfer none): a #GstCaps to set.
+ *
+ * Invoke the default setcaps function of the proxy pad.
+ *
+ * Returns: TRUE if the caps could be set. FALSE if the caps were not fixed
+ * or bad parameters were provided to this function.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_proxy_pad_setcaps_default (GstPad * pad, GstCaps * caps)
{
- GstPad *target = gst_proxy_pad_get_target (pad);
+ GstPad *target;
gboolean res;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+ g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
+
+ target = gst_proxy_pad_get_target (pad);
if (target) {
res = gst_pad_set_caps (target, caps);
gst_object_unref (target);
return target;
}
-static GstPad *
-gst_proxy_pad_get_internal (GstPad * pad)
+/**
+ * gst_proxy_pad_get_internal:
+ * @pad: the #GstProxyPad
+ *
+ * Get the internal pad of @pad. Unref target pad after usage.
+ *
+ * The internal pad of a #GstGhostPad is the internally used
+ * pad of opposite direction, which is used to link to the target.
+ *
+ * Returns: (transfer full): the target #GstProxyPad, can be NULL.
+ * Unref target pad after usage.
+ *
+ * Since: 0.10.35
+ */
+GstProxyPad *
+gst_proxy_pad_get_internal (GstProxyPad * pad)
{
GstPad *internal;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), NULL);
+
GST_PROXY_LOCK (pad);
internal = GST_PROXY_PAD_INTERNAL (pad);
if (internal)
gst_object_ref (internal);
GST_PROXY_UNLOCK (pad);
- return internal;
+ return GST_PROXY_PAD_CAST (internal);
}
-static void
-gst_proxy_pad_do_unlink (GstPad * pad)
+/**
+ * gst_proxy_pad_unlink_default:
+ * @pad: a #GstPad to unlink
+ *
+ * Invoke the default unlink function of the proxy pad.
+ *
+ * Since: 0.10.35
+ */
+void
+gst_proxy_pad_unlink_default (GstPad * pad)
{
GstPad *internal;
}
#endif
/* Register common function pointer descriptions */
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_query_type);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_event);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_query);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_iterate_internal_links);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_getcaps);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_acceptcaps);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_fixatecaps);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_setcaps);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_unlink);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_bufferalloc);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_chain);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_chain_list);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_getrange);
- GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_do_checkgetrange);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_type_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_event_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_query_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_iterate_internal_links_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getcaps_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_acceptcaps_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_fixatecaps_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_setcaps_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_unlink_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_bufferalloc_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_chain_list_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_getrange_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_proxy_pad_checkgetrange_default);
}
static void
GST_TYPE_PROXY_PAD, GstProxyPadPrivate);
GST_PROXY_GET_LOCK (pad) = g_mutex_new ();
- gst_pad_set_query_type_function (pad, gst_proxy_pad_do_query_type);
- gst_pad_set_event_function (pad, gst_proxy_pad_do_event);
- gst_pad_set_query_function (pad, gst_proxy_pad_do_query);
+ gst_pad_set_query_type_function (pad, gst_proxy_pad_query_type_default);
+ gst_pad_set_event_function (pad, gst_proxy_pad_event_default);
+ gst_pad_set_query_function (pad, gst_proxy_pad_query_default);
gst_pad_set_iterate_internal_links_function (pad,
- gst_proxy_pad_do_iterate_internal_links);
+ gst_proxy_pad_iterate_internal_links_default);
- gst_pad_set_getcaps_function (pad, gst_proxy_pad_do_getcaps);
- gst_pad_set_acceptcaps_function (pad, gst_proxy_pad_do_acceptcaps);
- gst_pad_set_fixatecaps_function (pad, gst_proxy_pad_do_fixatecaps);
- gst_pad_set_setcaps_function (pad, gst_proxy_pad_do_setcaps);
- gst_pad_set_unlink_function (pad, gst_proxy_pad_do_unlink);
+ gst_pad_set_getcaps_function (pad, gst_proxy_pad_getcaps_default);
+ gst_pad_set_acceptcaps_function (pad, gst_proxy_pad_acceptcaps_default);
+ gst_pad_set_fixatecaps_function (pad, gst_proxy_pad_fixatecaps_default);
+ gst_pad_set_setcaps_function (pad, gst_proxy_pad_setcaps_default);
+ gst_pad_set_unlink_function (pad, gst_proxy_pad_unlink_default);
}
#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED)
static void gst_ghost_pad_dispose (GObject * object);
-/* see gstghostpad design docs */
-static gboolean
-gst_ghost_pad_internal_do_activate_push (GstPad * pad, gboolean active)
+/**
+ * gst_ghost_pad_internal_activate_push_default:
+ * @pad: the #GstPad to activate or deactivate.
+ * @active: whether the pad should be active or not.
+ *
+ * Invoke the default activate push function of a proxy pad that is
+ * owned by a ghost pad.
+ *
+ * Returns: %TRUE if the operation was successful.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_ghost_pad_internal_activate_push_default (GstPad * pad, gboolean active)
{
gboolean ret;
GstPad *other;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+
GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, we're ok",
(active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
return ret;
}
-static gboolean
-gst_ghost_pad_internal_do_activate_pull (GstPad * pad, gboolean active)
+/**
+ * gst_ghost_pad_internal_activate_pull_default:
+ * @pad: the #GstPad to activate or deactivate.
+ * @active: whether the pad should be active or not.
+ *
+ * Invoke the default activate pull function of a proxy pad that is
+ * owned by a ghost pad.
+ *
+ * Returns: %TRUE if the operation was successful.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active)
{
gboolean ret;
GstPad *other;
+ g_return_val_if_fail (GST_IS_PROXY_PAD (pad), FALSE);
+
GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
GST_DEBUG_PAD_NAME (pad));
/* we are activated in pull mode by our peer element, which is a sinkpad
* that wants to operate in pull mode. This activation has to propagate
* upstream throught the pipeline. We call the internal activation function,
- * which will trigger gst_ghost_pad_do_activate_pull, which propagates even
+ * which will trigger gst_ghost_pad_activate_pull_default, which propagates even
* further upstream */
GST_LOG_OBJECT (pad, "pad is src, activate internal");
other = GST_PROXY_PAD_INTERNAL (pad);
return ret;
}
-static gboolean
-gst_ghost_pad_do_activate_push (GstPad * pad, gboolean active)
+/**
+ * gst_ghost_pad_activate_push_default:
+ * @pad: the #GstPad to activate or deactivate.
+ * @active: whether the pad should be active or not.
+ *
+ * Invoke the default activate push function of a ghost pad.
+ *
+ * Returns: %TRUE if the operation was successful.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_ghost_pad_activate_push_default (GstPad * pad, gboolean active)
{
gboolean ret;
GstPad *other;
+ g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
+
GST_LOG_OBJECT (pad, "%sactivate push on %s:%s, proxy internal",
(active ? "" : "de"), GST_DEBUG_PAD_NAME (pad));
return ret;
}
-static gboolean
-gst_ghost_pad_do_activate_pull (GstPad * pad, gboolean active)
+/**
+ * gst_ghost_pad_activate_pull_default:
+ * @pad: the #GstPad to activate or deactivate.
+ * @active: whether the pad should be active or not.
+ *
+ * Invoke the default activate pull function of a ghost pad.
+ *
+ * Returns: %TRUE if the operation was successful.
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_ghost_pad_activate_pull_default (GstPad * pad, gboolean active)
{
gboolean ret;
GstPad *other;
+ g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
+
GST_LOG_OBJECT (pad, "%sactivate pull on %s:%s", (active ? "" : "de"),
GST_DEBUG_PAD_NAME (pad));
return ret;
}
-static GstPadLinkReturn
-gst_ghost_pad_do_link (GstPad * pad, GstPad * peer)
+/**
+ * gst_ghost_pad_link_default:
+ * @pad: the #GstPad to link.
+ * @peer: the #GstPad peer
+ *
+ * Invoke the default link function of a ghost pad.
+ *
+ * Returns: #GstPadLinkReturn of the operation
+ *
+ * Since: 0.10.35
+ */
+GstPadLinkReturn
+gst_ghost_pad_link_default (GstPad * pad, GstPad * peer)
{
GstPadLinkReturn ret;
GstPad *internal;
+ g_return_val_if_fail (GST_IS_GHOST_PAD (pad), GST_PAD_LINK_REFUSED);
+ g_return_val_if_fail (GST_IS_PAD (peer), GST_PAD_LINK_REFUSED);
+
GST_DEBUG_OBJECT (pad, "linking ghostpad");
internal = GST_PROXY_PAD_INTERNAL (pad);
}
}
-static void
-gst_ghost_pad_do_unlink (GstPad * pad)
+/**
+ * gst_ghost_pad_unlink_default:
+ * @pad: the #GstPad to link.
+ *
+ * Invoke the default unlink function of a ghost pad.
+ *
+ * Since: 0.10.35
+ */
+void
+gst_ghost_pad_unlink_default (GstPad * pad)
{
GstPad *internal;
+ g_return_if_fail (GST_IS_GHOST_PAD (pad));
+
internal = GST_PROXY_PAD_INTERNAL (pad);
GST_DEBUG_OBJECT (pad, "unlinking ghostpad");
gst_caps_unref (caps);
}
-static gboolean
-gst_ghost_pad_do_setcaps (GstPad * pad, GstCaps * caps)
+/**
+ * gst_ghost_pad_setcaps_default:
+ * @pad: the #GstPad to link.
+ * @caps: (transfer none): the #GstCaps to set
+ *
+ * Invoke the default setcaps function of a ghost pad.
+ *
+ * Returns: %TRUE if the operation was successful
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_ghost_pad_setcaps_default (GstPad * pad, GstCaps * caps)
{
+ g_return_val_if_fail (GST_IS_GHOST_PAD (pad), FALSE);
+ g_return_val_if_fail (caps == NULL || GST_IS_CAPS (caps), FALSE);
+
if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
return TRUE;
- return gst_proxy_pad_do_setcaps (pad, caps);
-}
-
-static GstIterator *
-gst_ghost_pad_do_iterate_internal_links (GstPad * pad)
-{
- GstIterator *res = NULL;
- GstPad *internal = GST_PROXY_PAD_INTERNAL (GST_GHOST_PAD_CAST (pad));
-
- if (internal) {
- res =
- gst_iterator_new_single (GST_TYPE_PAD, internal,
- (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref);
- }
-
- return res;
+ return gst_proxy_pad_setcaps_default (pad, caps);
}
static void
gobject_class->dispose = gst_ghost_pad_dispose;
- GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_do_setcaps);
- GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_do_activate_pull);
- GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_do_activate_push);
- GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_do_link);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_setcaps_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_pull_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_activate_push_default);
+ GST_DEBUG_REGISTER_FUNCPTR (gst_ghost_pad_link_default);
}
static void
GST_GHOST_PAD_PRIVATE (pad) = G_TYPE_INSTANCE_GET_PRIVATE (pad,
GST_TYPE_GHOST_PAD, GstGhostPadPrivate);
- gst_pad_set_setcaps_function (GST_PAD_CAST (pad), gst_ghost_pad_do_setcaps);
+ gst_pad_set_setcaps_function (GST_PAD_CAST (pad),
+ gst_ghost_pad_setcaps_default);
gst_pad_set_activatepull_function (GST_PAD_CAST (pad),
- gst_ghost_pad_do_activate_pull);
+ gst_ghost_pad_activate_pull_default);
gst_pad_set_activatepush_function (GST_PAD_CAST (pad),
- gst_ghost_pad_do_activate_push);
- gst_pad_set_iterate_internal_links_function (GST_PAD_CAST (pad),
- gst_ghost_pad_do_iterate_internal_links);
+ gst_ghost_pad_activate_push_default);
}
static void
gst_ghost_pad_set_target (GST_GHOST_PAD (pad), NULL);
/* Unlink here so that gst_pad_dispose doesn't. That would lead to a call to
- * gst_ghost_pad_do_unlink when the ghost pad is in an inconsistent state */
+ * gst_ghost_pad_unlink_default when the ghost pad is in an inconsistent state */
peer = gst_pad_get_peer (pad);
if (peer) {
if (GST_PAD_IS_SRC (pad))
/* Set directional padfunctions for ghostpad */
if (dir == GST_PAD_SINK) {
- gst_pad_set_bufferalloc_function (pad, gst_proxy_pad_do_bufferalloc);
- gst_pad_set_chain_function (pad, gst_proxy_pad_do_chain);
- gst_pad_set_chain_list_function (pad, gst_proxy_pad_do_chain_list);
+ gst_pad_set_bufferalloc_function (pad, gst_proxy_pad_bufferalloc_default);
+ gst_pad_set_chain_function (pad, gst_proxy_pad_chain_default);
+ gst_pad_set_chain_list_function (pad, gst_proxy_pad_chain_list_default);
} else {
- gst_pad_set_getrange_function (pad, gst_proxy_pad_do_getrange);
- gst_pad_set_checkgetrange_function (pad, gst_proxy_pad_do_checkgetrange);
+ gst_pad_set_getrange_function (pad, gst_proxy_pad_getrange_default);
+ gst_pad_set_checkgetrange_function (pad,
+ gst_proxy_pad_checkgetrange_default);
}
/* link/unlink functions */
- gst_pad_set_link_function (pad, gst_ghost_pad_do_link);
- gst_pad_set_unlink_function (pad, gst_ghost_pad_do_unlink);
+ gst_pad_set_link_function (pad, gst_ghost_pad_link_default);
+ gst_pad_set_unlink_function (pad, gst_ghost_pad_unlink_default);
/* INTERNAL PAD, it always exists and is child of the ghostpad */
otherdir = (dir == GST_PAD_SRC) ? GST_PAD_SINK : GST_PAD_SRC;
/* Set directional padfunctions for internal pad */
if (dir == GST_PAD_SRC) {
- gst_pad_set_bufferalloc_function (internal, gst_proxy_pad_do_bufferalloc);
- gst_pad_set_chain_function (internal, gst_proxy_pad_do_chain);
- gst_pad_set_chain_list_function (internal, gst_proxy_pad_do_chain_list);
+ gst_pad_set_bufferalloc_function (internal,
+ gst_proxy_pad_bufferalloc_default);
+ gst_pad_set_chain_function (internal, gst_proxy_pad_chain_default);
+ gst_pad_set_chain_list_function (internal,
+ gst_proxy_pad_chain_list_default);
} else {
- gst_pad_set_getrange_function (internal, gst_proxy_pad_do_getrange);
+ gst_pad_set_getrange_function (internal, gst_proxy_pad_getrange_default);
gst_pad_set_checkgetrange_function (internal,
- gst_proxy_pad_do_checkgetrange);
+ gst_proxy_pad_checkgetrange_default);
}
GST_PROXY_LOCK (pad);
/* special activation functions for the internal pad */
gst_pad_set_activatepull_function (internal,
- gst_ghost_pad_internal_do_activate_pull);
+ gst_ghost_pad_internal_activate_pull_default);
gst_pad_set_activatepush_function (internal,
- gst_ghost_pad_internal_do_activate_push);
+ gst_ghost_pad_internal_activate_push_default);
GST_PROXY_UNLOCK (pad);
diff --git a/gst/gstghostpad.h b/gst/gstghostpad.h
index f492a74b59973a51c66a52112ceb5c24ce09b78a..308ab70cb65f17f6e059efa2ebccab0b54c82d2e 100644 (file)
--- a/gst/gstghostpad.h
+++ b/gst/gstghostpad.h
GType gst_proxy_pad_get_type (void);
+GstProxyPad* gst_proxy_pad_get_internal (GstProxyPad *pad);
+
+
+const GstQueryType* gst_proxy_pad_query_type_default (GstPad *pad);
+gboolean gst_proxy_pad_event_default (GstPad *pad, GstEvent *event);
+gboolean gst_proxy_pad_query_default (GstPad *pad, GstQuery *query);
+GstIterator* gst_proxy_pad_iterate_internal_links_default (GstPad *pad);
+GstFlowReturn gst_proxy_pad_bufferalloc_default (GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf);
+GstFlowReturn gst_proxy_pad_chain_default (GstPad *pad, GstBuffer *buffer);
+GstFlowReturn gst_proxy_pad_chain_list_default (GstPad *pad, GstBufferList *list);
+GstFlowReturn gst_proxy_pad_getrange_default (GstPad *pad, guint64 offset, guint size, GstBuffer **buffer);
+gboolean gst_proxy_pad_checkgetrange_default (GstPad *pad);
+GstCaps* gst_proxy_pad_getcaps_default (GstPad *pad);
+gboolean gst_proxy_pad_acceptcaps_default (GstPad *pad, GstCaps *caps);
+void gst_proxy_pad_fixatecaps_default (GstPad *pad, GstCaps *caps);
+gboolean gst_proxy_pad_setcaps_default (GstPad *pad, GstCaps *caps);
+void gst_proxy_pad_unlink_default (GstPad * pad);
#define GST_TYPE_GHOST_PAD (gst_ghost_pad_get_type ())
#define GST_IS_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GHOST_PAD))
gboolean gst_ghost_pad_construct (GstGhostPad *gpad);
+gboolean gst_ghost_pad_setcaps_default (GstPad * pad, GstCaps * caps);
+void gst_ghost_pad_unlink_default (GstPad * pad);
+GstPadLinkReturn gst_ghost_pad_link_default (GstPad * pad, GstPad * peer);
+gboolean gst_ghost_pad_activate_pull_default (GstPad * pad, gboolean active);
+gboolean gst_ghost_pad_activate_push_default (GstPad * pad, gboolean active);
+
+gboolean gst_ghost_pad_internal_activate_push_default (GstPad * pad, gboolean active);
+gboolean gst_ghost_pad_internal_activate_pull_default (GstPad * pad, gboolean active);
+
G_END_DECLS
#endif /* __GST_GHOST_PAD_H__ */
diff --git a/gst/gstmessage.h b/gst/gstmessage.h
index 0eafac52df185c7ed6741e1f5aa88644404f7375..757b1d5bed9c63d7460be5c554ac6fdcdcf38ec6 100644 (file)
--- a/gst/gstmessage.h
+++ b/gst/gstmessage.h
* @GST_MESSAGE_SEGMENT_START posted a GST_MESSAGE_SEGMENT_DONE message.
* @GST_MESSAGE_DURATION: The duration of a pipeline changed. The application
* can get the new duration with a duration query.
- * @GST_MESSAGE_ASYNC_START: Posted by elements when they start an ASYNC state
- * change. This message is not forwarded to the application but is used
+ * @GST_MESSAGE_ASYNC_START: Posted by elements when they start an ASYNC
+ * #GstStateChange. This message is not forwarded to the application but is used
* internally. Since: 0.10.13.
- * @GST_MESSAGE_ASYNC_DONE: Posted by elements when they complete an ASYNC state
- * change. The application will only receive this message from the toplevel
+ * @GST_MESSAGE_ASYNC_DONE: Posted by elements when they complete an ASYNC
+ * #GstStateChange. The application will only receive this message from the toplevel
* pipeline. Since: 0.10.13
* @GST_MESSAGE_LATENCY: Posted by elements when their latency changes. The
* application should recalculate and distribute a new latency. Since: 0.10.12
diff --git a/gst/gstminiobject.c b/gst/gstminiobject.c
index 4b46d292977749dc450d15803b46ed98e071faef..3993e02a718ca47984506d9485ad0ce2a8b0ec8b 100644 (file)
--- a/gst/gstminiobject.c
+++ b/gst/gstminiobject.c
#define GST_MINI_OBJECT_GET_CLASS_UNCHECKED(obj) \
((GstMiniObjectClass *) (((GTypeInstance*)(obj))->g_class))
+/* Structure used for storing weak references */
+typedef struct
+{
+ GstMiniObject *object;
+ guint n_weak_refs;
+ struct
+ {
+ GstMiniObjectWeakNotify notify;
+ gpointer data;
+ } weak_refs[1]; /* flexible array */
+} WeakRefStack;
+
+/* Structure for storing a mini object's private data */
+struct _GstMiniObjectPrivate
+{
+ WeakRefStack *wstack;
+};
+
#if 0
static void gst_mini_object_base_init (gpointer g_class);
static void gst_mini_object_base_finalize (gpointer g_class);
static void gst_value_mini_object_init (GValue * value);
static void gst_value_mini_object_free (GValue * value);
+static void weak_refs_notify (WeakRefStack * data);
static void gst_value_mini_object_copy (const GValue * src_value,
GValue * dest_value);
static gpointer gst_value_mini_object_peek_pointer (const GValue * value);
static GstMiniObject *gst_mini_object_copy_default (const GstMiniObject * obj);
static void gst_mini_object_finalize (GstMiniObject * obj);
+/* Mutex used for weak referencing */
+G_LOCK_DEFINE_STATIC (weak_refs_mutex);
+
GType
gst_mini_object_get_type (void)
{
mo_class->copy = gst_mini_object_copy_default;
mo_class->finalize = gst_mini_object_finalize;
+
+ /* Set the instance data type */
+ g_type_class_add_private (g_class, sizeof (GstMiniObjectPrivate));
}
static void
GstMiniObject *mini_object = GST_MINI_OBJECT_CAST (instance);
mini_object->refcount = 1;
+
+ /* we delay initialising the mini object's private data until it's actually
+ * needed for now (mini_object->priv automatically inited to NULL) */
}
static GstMiniObject *
return mini_object;
}
+static void
+weak_refs_notify (WeakRefStack * wstack)
+{
+ guint i;
+
+ for (i = 0; i < wstack->n_weak_refs; i++)
+ wstack->weak_refs[i].notify (wstack->weak_refs[i].data, wstack->object);
+ g_free (wstack);
+}
+
static void
gst_mini_object_free (GstMiniObject * mini_object)
{
/* decrement the refcount again, if the subclass recycled the object we don't
* want to free the instance anymore */
if (G_LIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
+ /* The weak reference stack is freed in the notification function */
+ if (mini_object->priv != NULL && mini_object->priv->wstack != NULL)
+ weak_refs_notify (mini_object->priv->wstack);
+
#ifndef GST_DISABLE_TRACE
gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
#endif
}
}
+/**
+ * gst_mini_object_weak_ref: (skip)
+ * @object: #GstMiniObject to reference weakly
+ * @notify: callback to invoke before the mini object is freed
+ * @data: extra data to pass to notify
+ *
+ * Adds a weak reference callback to a mini object. Weak references are
+ * used for notification when a mini object is finalized. They are called
+ * "weak references" because they allow you to safely hold a pointer
+ * to the mini object without calling gst_mini_object_ref()
+ * (gst_mini_object_ref() adds a strong reference, that is, forces the object
+ * to stay alive).
+ *
+ * Since: 0.10.35
+ */
+void
+gst_mini_object_weak_ref (GstMiniObject * object,
+ GstMiniObjectWeakNotify notify, gpointer data)
+{
+ guint i;
+
+ g_return_if_fail (GST_IS_MINI_OBJECT (object));
+ g_return_if_fail (notify != NULL);
+ g_return_if_fail (GST_MINI_OBJECT_REFCOUNT_VALUE (object) >= 1);
+
+ G_LOCK (weak_refs_mutex);
+
+ if (object->priv == NULL) {
+ object->priv = G_TYPE_INSTANCE_GET_PRIVATE (object, GST_TYPE_MINI_OBJECT,
+ GstMiniObjectPrivate);
+
+ /* object->priv->wstack will have been inited to NULL automatically */
+ }
+
+ if (object->priv->wstack) {
+ /* Don't add the weak reference if it already exists. */
+ for (i = 0; i < object->priv->wstack->n_weak_refs; i++) {
+ if (object->priv->wstack->weak_refs[i].notify == notify &&
+ object->priv->wstack->weak_refs[i].data == data) {
+ g_warning ("%s: Attempt to re-add existing weak ref %p(%p) failed.",
+ G_STRFUNC, notify, data);
+ goto found;
+ }
+ }
+
+ i = object->priv->wstack->n_weak_refs++;
+ object->priv->wstack =
+ g_realloc (object->priv->wstack, sizeof (*(object->priv->wstack)) +
+ sizeof (object->priv->wstack->weak_refs[0]) * i);
+ } else {
+ object->priv->wstack = g_renew (WeakRefStack, NULL, 1);
+ object->priv->wstack->object = object;
+ object->priv->wstack->n_weak_refs = 1;
+ i = 0;
+ }
+ object->priv->wstack->weak_refs[i].notify = notify;
+ object->priv->wstack->weak_refs[i].data = data;
+found:
+ G_UNLOCK (weak_refs_mutex);
+}
+
+/**
+ * gst_mini_object_weak_unref: (skip)
+ * @object: #GstMiniObject to remove a weak reference from
+ * @notify: callback to search for
+ * @data: data to search for
+ *
+ * Removes a weak reference callback to a mini object.
+ *
+ * Since: 0.10.35
+ */
+void
+gst_mini_object_weak_unref (GstMiniObject * object,
+ GstMiniObjectWeakNotify notify, gpointer data)
+{
+ gboolean found_one = FALSE;
+
+ g_return_if_fail (GST_IS_MINI_OBJECT (object));
+ g_return_if_fail (notify != NULL);
+
+ G_LOCK (weak_refs_mutex);
+
+ if (object->priv != NULL && object->priv->wstack != NULL) {
+ guint i;
+
+ for (i = 0; i < object->priv->wstack->n_weak_refs; i++)
+ if (object->priv->wstack->weak_refs[i].notify == notify &&
+ object->priv->wstack->weak_refs[i].data == data) {
+ found_one = TRUE;
+ object->priv->wstack->n_weak_refs -= 1;
+ if (i != object->priv->wstack->n_weak_refs)
+ object->priv->wstack->weak_refs[i] =
+ object->priv->wstack->weak_refs[object->priv->wstack->
+ n_weak_refs];
+
+ break;
+ }
+ }
+ G_UNLOCK (weak_refs_mutex);
+ if (!found_one)
+ g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
+}
+
/**
* gst_mini_object_replace:
* @olddata: (inout) (transfer full): pointer to a pointer to a mini-object to
{
if (src_value->data[0].v_pointer) {
dest_value->data[0].v_pointer =
- gst_mini_object_ref (GST_MINI_OBJECT_CAST (src_value->
- data[0].v_pointer));
+ gst_mini_object_ref (GST_MINI_OBJECT_CAST (src_value->data[0].
+ v_pointer));
} else {
dest_value->data[0].v_pointer = NULL;
}
{
g_return_val_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value), NULL);
- return value->data[0].v_pointer ? gst_mini_object_ref (value->data[0].
- v_pointer) : NULL;
+ return value->data[0].v_pointer ? gst_mini_object_ref (value->
+ data[0].v_pointer) : NULL;
}
diff --git a/gst/gstminiobject.h b/gst/gstminiobject.h
index 1005dc544253f968e5eb5fa1ea04b072230ae87b..024d1e21111f529925e8b08ba8d483fe3df5aaab 100644 (file)
--- a/gst/gstminiobject.h
+++ b/gst/gstminiobject.h
*/
#define GST_MINI_OBJECT_REFCOUNT_VALUE(obj) (g_atomic_int_get (&(GST_MINI_OBJECT_CAST(obj))->refcount))
+/**
+ * GstMiniObjectWeakNotify:
+ * @data: data that was provided when the weak reference was established
+ * @where_the_mini_object_was: the mini object being finalized
+ *
+ * A #GstMiniObjectWeakNotify function can be added to a mini object as a
+ * callback that gets triggered when the mini object is finalized. Since the
+ * mini object is already being finalized when the #GstMiniObjectWeakNotify is
+ * called, there's not much you could do with the object, apart from e.g. using
+ * its adress as hash-index or the like.
+ *
+ * Since: 0.10.35
+ *
+ */
+typedef void (*GstMiniObjectWeakNotify) (gpointer data,
+ GstMiniObject * where_the_mini_object_was);
+
+typedef struct _GstMiniObjectPrivate GstMiniObjectPrivate;
+
/**
* GstMiniObject:
* @instance: type instance
guint flags;
/*< private >*/
- gpointer _gst_reserved;
+ GstMiniObjectPrivate *priv;
};
struct _GstMiniObjectClass {
/* refcounting */
GstMiniObject* gst_mini_object_ref (GstMiniObject *mini_object);
void gst_mini_object_unref (GstMiniObject *mini_object);
+void gst_mini_object_weak_ref (GstMiniObject *object,
+ GstMiniObjectWeakNotify notify,
+ gpointer data);
+void gst_mini_object_weak_unref (GstMiniObject *object,
+ GstMiniObjectWeakNotify notify,
+ gpointer data);
void gst_mini_object_replace (GstMiniObject **olddata, GstMiniObject *newdata);
/* GParamSpec */
diff --git a/gst/gstpad.c b/gst/gstpad.c
index c18448540e4653743dc33d1c09040742f23c1948..14c97863ef6371a53d9e5a6896d39fee6d8a5039 100644 (file)
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
* take an indeterminate amount of time.
* You can pass NULL as the callback to make this call block. Be careful with
* this blocking call as it might not return for reasons stated above.
- *
+ *
* <note>
* Pad block handlers are only called for source pads in push mode
* and sink pads in pull mode.
* @sinkpad: the sink #GstPad.
*
* Checks if the source pad and the sink pad are compatible so they can be
- * linked.
+ * linked.
*
* Returns: TRUE if the pads can be linked.
*/
* two concurrent iterators were used and the last iterator would still be
* thread-unsafe. Just don't use this method anymore. */
data = g_slice_new (IntLinkIterData);
- data->list = GST_PAD_INTLINKFUNC (pad) (pad);
+ data->list = ((GstPadIntLinkFunction) GST_PAD_INTLINKFUNC (pad)) (pad);
data->cookie = 0;
GST_WARNING_OBJECT (pad, "Making unsafe iterator");
* Deprecated: This function does not ref the pads in the list so that they
* could become invalid by the time the application accesses them. It's also
* possible that the list changes while handling the pads, which the caller of
- * this function is unable to know. Use the thread-safe
+ * this function is unable to know. Use the thread-safe
* gst_pad_iterate_internal_links_default() instead.
*/
#ifndef GST_REMOVE_DEPRECATED
*
* Returns: (transfer full) (element-type Gst.Pad): a newly allocated #GList
* of pads, free with g_list_free().
- *
+ *
* Deprecated: This function does not ref the pads in the list so that they
* could become invalid by the time the application accesses them. It's also
* possible that the list changes while handling the pads, which the caller of
- * this function is unable to know. Use the thread-safe
+ * this function is unable to know. Use the thread-safe
* gst_pad_iterate_internal_links() instead.
*/
#ifndef GST_REMOVE_DEPRECATED
GST_WARNING_OBJECT (pad, "Calling unsafe internal links");
if (GST_PAD_INTLINKFUNC (pad))
- res = GST_PAD_INTLINKFUNC (pad) (pad);
+ res = ((GstPadIntLinkFunction) GST_PAD_INTLINKFUNC (pad)) (pad);
return res;
}
gst_object_unref (item);
break;
case GST_ITERATOR_RESYNC:
- /* FIXME, if we want to reset the result value we need to remember which
- * pads pushed with which result */
+ /* We don't reset the result here because we don't push the event
+ * again on pads that got the event already and because we need
+ * to consider the result of the previous pushes */
gst_iterator_resync (iter);
break;
case GST_ITERATOR_ERROR:
diff --git a/gst/gstpad.h b/gst/gstpad.h
index 19834c41d39cecfd2674102a8edc29ca474057d5..5317dee41c341c5273019bd9d7fa9f7b01a9f884 100644 (file)
--- a/gst/gstpad.h
+++ b/gst/gstpad.h
* @GST_PAD_LINK_CHECK_NOTHING: Don't check hierarchy or caps compatibility.
* @GST_PAD_LINK_CHECK_HIERARCHY: Check the pads have same parents/grandparents.
* Could be omitted if it is already known that the two elements that own the
- * pads are in the same bin.
+ * pads are in the same bin.
* @GST_PAD_LINK_CHECK_TEMPLATE_CAPS: Check if the pads are compatible by using
* their template caps. This is much faster than @GST_PAD_LINK_CHECK_CAPS, but
* would be unsafe e.g. if one pad has %GST_CAPS_ANY.
/**
* GST_PAD_LINK_CHECK_DEFAULT:
*
- * The default checks done when linking pads (i.e. the ones used by
+ * The default checks done when linking pads (i.e. the ones used by
* gst_pad_link()).
*
* Since: 0.10.30
*
* Deprecated: use the threadsafe #GstPadIterIntLinkFunction instead.
*/
+#ifndef GST_DISABLE_DEPRECATED
typedef GList* (*GstPadIntLinkFunction) (GstPad *pad);
+#endif
+
/**
* GstPadIterIntLinkFunction:
GstPadQueryFunction queryfunc;
/* internal links */
+#ifndef GST_DISABLE_DEPRECATED
GstPadIntLinkFunction intlinkfunc;
+#else
+#ifndef __GTK_DOC_IGNORE__
+ gpointer intlinkfunc;
+#endif
+#endif
GstPadBufferAllocFunction bufferallocfunc;
diff --git a/gst/gstpluginfeature.c b/gst/gstpluginfeature.c
index 3c62b1b08e908c0e16c7117af74672235e94090c..c72a1f77800db59f4ffb92055c5e120079d1d5da 100644 (file)
--- a/gst/gstpluginfeature.c
+++ b/gst/gstpluginfeature.c
GST_DEBUG ("finalizing feature %p: '%s'", feature,
GST_PLUGIN_FEATURE_NAME (feature));
- g_free (feature->name);
if (feature->plugin != NULL) {
g_object_remove_weak_pointer ((GObject *) feature->plugin,
* Normally this function is used like this:
* |[
* GstPluginFeature *loaded_feature;
- *
+ *
* loaded_feature = gst_plugin_feature_load (feature);
* // presumably, we're no longer interested in the potentially-unloaded feature
* gst_object_unref (feature);
g_return_if_fail (GST_IS_PLUGIN_FEATURE (feature));
g_return_if_fail (name != NULL);
- if (feature->name) {
+ if (G_UNLIKELY (feature->name)) {
g_return_if_fail (strcmp (feature->name, name) == 0);
} else {
- feature->name = g_strdup (name);
+ gst_object_set_name (GST_OBJECT (feature), name);
+ feature->name = GST_OBJECT_NAME (GST_OBJECT (feature));
}
- gst_object_set_name (GST_OBJECT_CAST (feature), feature->name);
}
/**
diff --git a/gst/gstpluginfeature.h b/gst/gstpluginfeature.h
index 177c8bd3a3887c89517d24d782d97d90c1c8ccad..baf592c8a7732b1b6a02f386da53ca75342c7757 100644 (file)
--- a/gst/gstpluginfeature.h
+++ b/gst/gstpluginfeature.h
/*< private >*/
gboolean loaded;
- gchar *name;
+ gchar *name; /* FIXME-0.11: remove variable, we use GstObject:name */
guint rank;
const gchar *plugin_name;
diff --git a/gst/gstpreset.c b/gst/gstpreset.c
index d566065734890aaeb7759091e2e927cac9c61768..811e4d18612692c40149569e459a39dbca06471b 100644 (file)
--- a/gst/gstpreset.c
+++ b/gst/gstpreset.c
#include "gst_private.h"
#include "gstpreset.h"
+#include "gstinfo.h"
+#include "gstvalue.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
static guint64
preset_parse_version (const gchar * str_version)
{
- gint major, minor, micro, nano, num;
+ guint major, minor, micro, nano;
+ gint num;
major = minor = micro = nano = 0;
/* parse version (e.g. 0.10.15.1) to guint64 */
- num = sscanf (str_version, "%d.%d.%d.%d", &major, &minor, µ, &nano);
+ num = sscanf (str_version, "%u.%u.%u.%u", &major, &minor, µ, &nano);
/* make sure we have atleast "major.minor" */
if (num > 1) {
guint64 version;
diff --git a/gst/gstpreset.h b/gst/gstpreset.h
index 73816326bd0fb8dc5052eaf2c37b0f8f0a3a79b0..ccf1366f66b5d747dc32670a1300b979a94069f3 100644 (file)
--- a/gst/gstpreset.h
+++ b/gst/gstpreset.h
#define __GST_PRESET_H__
#include <glib-object.h>
-#include <gst/gst.h>
G_BEGIN_DECLS
diff --git a/gst/gstregistry.c b/gst/gstregistry.c
index 5b6df92f3b539cb5ab4a47fbe92b785e9c389513..0955ae1621143cd1967a490e1428670412ab1277 100644 (file)
--- a/gst/gstregistry.c
+++ b/gst/gstregistry.c
* means of doing so is to load every plugin and look at the resulting
* information that is gathered in the default registry. Clearly, this is a time
* consuming process, so we cache information in the registry file. The format
- * and location of the cache file is internal to gstreamer.
+ * and location of the cache file is internal to gstreamer.
*
* On startup, plugins are searched for in the plugin search path. The following
* locations are checked in this order:
if (feature) {
GST_LOG_OBJECT (registry, "removing feature %p (%s)",
feature, gst_plugin_feature_get_name (feature));
- gst_object_unref (feature);
+ gst_object_unparent (GST_OBJECT_CAST (feature));
}
f = g_list_next (f);
}
registry->features = g_list_delete_link (registry->features, f);
g_hash_table_remove (registry->feature_hash, feature->name);
- gst_object_unref (feature);
+ gst_object_unparent (GST_OBJECT_CAST (feature));
}
f = next;
}
if (G_UNLIKELY (existing_feature)) {
/* We unref now. No need to remove the feature name from the hash table, it
* got replaced by the new feature */
- gst_object_unref (existing_feature);
+ gst_object_unparent (GST_OBJECT_CAST (existing_feature));
}
- gst_object_ref_sink (feature);
+ gst_object_set_parent (GST_OBJECT_CAST (feature), GST_OBJECT_CAST (registry));
registry->priv->cookie++;
GST_OBJECT_UNLOCK (registry);
@@ -598,7 +598,8 @@ gst_registry_remove_feature (GstRegistry * registry, GstPluginFeature * feature)
g_hash_table_remove (registry->feature_hash, feature->name);
registry->priv->cookie++;
GST_OBJECT_UNLOCK (registry);
- gst_object_unref (feature);
+
+ gst_object_unparent ((GstObject *) feature);
}
/**
index a367f4100b65eba1c36ef833f0117010138557c8..aa2c6d31ff9379f614d6bdc4a4a332546a617b7c 100644 (file)
--- a/gst/gstregistrybinary.h
+++ b/gst/gstregistrybinary.h
* This _must_ be updated whenever the registry format changes,
* we currently use the core version where this change happened.
*/
-#define GST_MAGIC_BINARY_VERSION_STR ("0.10.30.1")
+#define GST_MAGIC_BINARY_VERSION_STR "0.10.30.1"
/*
* GST_MAGIC_BINARY_VERSION_LEN:
*
- * length of the version string.
+ * Maximum length of the version string in the header.
*/
#define GST_MAGIC_BINARY_VERSION_LEN (64)
index d30d4004ba0dd545b2f50475ef9e4a2aebdec6ad..684a18153c24eb839ed8bee5f12c3401b0d286ed 100644 (file)
--- a/gst/gstregistrychunks.c
+++ b/gst/gstregistrychunks.c
GstRegistryChunkPluginFeature *pf = NULL;
GstPluginFeature *feature = NULL;
const gchar *const_str, *type_name;
+ const gchar *feature_name;
const gchar *plugin_name;
- gchar *str, *feature_name;
+ gchar *str;
GType type;
guint i;
}
/* unpack more plugin feature strings */
- unpack_string (*in, feature_name, end, fail);
+ unpack_string_nocopy (*in, feature_name, end, fail);
GST_DEBUG ("Plugin '%s' feature '%s' typename : '%s'", plugin_name,
feature_name, type_name);
if (G_UNLIKELY (!(type = g_type_from_name (type_name)))) {
GST_ERROR ("Unknown type from typename '%s' for plugin '%s'", type_name,
plugin_name);
- g_free (feature_name);
return FALSE;
}
if (G_UNLIKELY ((feature = g_object_newv (type, 0, NULL)) == NULL)) {
GST_ERROR ("Can't create feature from type");
- g_free (feature_name);
return FALSE;
}
-
- feature->name = feature_name;
+ gst_plugin_feature_set_name (feature, feature_name);
if (G_UNLIKELY (!GST_IS_PLUGIN_FEATURE (feature))) {
GST_ERROR ("typename : '%s' is not a plugin feature", type_name);
diff --git a/gst/gststructure.c b/gst/gststructure.c
index f0ff914fefaf308c9632ac03d83bb2fbee17a1c3..3b2c2e41216e65f68adec17379cf38ce77bd9378 100644 (file)
--- a/gst/gststructure.c
+++ b/gst/gststructure.c
g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
type = GST_TYPE_DATE;
}
-#if GLIB_CHECK_VERSION(2,23,3)
G_VALUE_COLLECT_INIT (&field.value, type, varargs, 0, &err);
-#else
- g_value_init (&field.value, type);
- G_VALUE_COLLECT (&field.value, varargs, 0, &err);
-#endif
if (G_UNLIKELY (err)) {
g_critical ("%s", err);
return;
@@ -2916,3 +2911,262 @@ gst_structure_id_get (const GstStructure * structure, GQuark first_field_id,
return ret;
}
+
+static gboolean
+gst_structure_is_equal_foreach (GQuark field_id, const GValue * val2,
+ gpointer data)
+{
+ const GstStructure *struct1 = (const GstStructure *) data;
+ const GValue *val1 = gst_structure_id_get_value (struct1, field_id);
+
+ if (G_UNLIKELY (val1 == NULL))
+ return FALSE;
+ if (gst_value_compare (val1, val2) == GST_VALUE_EQUAL) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * gst_structure_is_equal:
+ * @structure1: a #GstStructure.
+ * @structure2: a #GstStructure.
+ *
+ * Tests if the two #GstStructure are equal.
+ *
+ * Returns: TRUE if the two structures have the same name and field.
+ *
+ * Since: 0.10.35
+ **/
+gboolean
+gst_structure_is_equal (const GstStructure * structure1,
+ const GstStructure * structure2)
+{
+ g_return_val_if_fail (GST_IS_STRUCTURE (structure1), FALSE);
+ g_return_val_if_fail (GST_IS_STRUCTURE (structure2), FALSE);
+
+ if (structure1->name != structure2->name) {
+ return FALSE;
+ }
+ if (structure1->fields->len != structure2->fields->len) {
+ return FALSE;
+ }
+
+ return gst_structure_foreach (structure1, gst_structure_is_equal_foreach,
+ (gpointer) structure2);
+}
+
+
+typedef struct
+{
+ GstStructure *dest;
+ const GstStructure *intersect;
+}
+IntersectData;
+
+static gboolean
+gst_structure_intersect_field1 (GQuark id, const GValue * val1, gpointer data)
+{
+ IntersectData *idata = (IntersectData *) data;
+ const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
+
+ if (G_UNLIKELY (val2 == NULL)) {
+ gst_structure_id_set_value (idata->dest, id, val1);
+ } else {
+ GValue dest_value = { 0 };
+ if (gst_value_intersect (&dest_value, val1, val2)) {
+ gst_structure_id_set_value (idata->dest, id, &dest_value);
+ g_value_unset (&dest_value);
+ } else {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static gboolean
+gst_structure_intersect_field2 (GQuark id, const GValue * val1, gpointer data)
+{
+ IntersectData *idata = (IntersectData *) data;
+ const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
+
+ if (G_UNLIKELY (val2 == NULL)) {
+ gst_structure_id_set_value (idata->dest, id, val1);
+ }
+ return TRUE;
+}
+
+/**
+ * gst_structure_intersect:
+ * @struct1: a #GstStructure
+ * @struct2: a #GstStructure
+ *
+ * Interesects @struct1 and @struct2 and returns the intersection.
+ *
+ * Returns: Intersection of @struct1 and @struct2
+ *
+ * Since: 0.10.35
+ */
+GstStructure *
+gst_structure_intersect (const GstStructure * struct1,
+ const GstStructure * struct2)
+{
+ IntersectData data;
+
+ g_assert (struct1 != NULL);
+ g_assert (struct2 != NULL);
+
+ if (G_UNLIKELY (struct1->name != struct2->name))
+ return NULL;
+
+ /* copy fields from struct1 which we have not in struct2 to target
+ * intersect if we have the field in both */
+ data.dest = gst_structure_id_empty_new (struct1->name);
+ data.intersect = struct2;
+ if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
+ gst_structure_intersect_field1, &data)))
+ goto error;
+
+ /* copy fields from struct2 which we have not in struct1 to target */
+ data.intersect = struct1;
+ if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2,
+ gst_structure_intersect_field2, &data)))
+ goto error;
+
+ return data.dest;
+
+error:
+ gst_structure_free (data.dest);
+ return NULL;
+}
+
+static gboolean
+gst_caps_structure_can_intersect_field (GQuark id, const GValue * val1,
+ gpointer data)
+{
+ GstStructure *other = (GstStructure *) data;
+ const GValue *val2 = gst_structure_id_get_value (other, id);
+
+ if (G_LIKELY (val2)) {
+ if (!gst_value_can_intersect (val1, val2)) {
+ return FALSE;
+ } else {
+ gint eq = gst_value_compare (val1, val2);
+
+ if (eq == GST_VALUE_UNORDERED) {
+ /* we need to try interseting */
+ GValue dest_value = { 0 };
+ if (gst_value_intersect (&dest_value, val1, val2)) {
+ g_value_unset (&dest_value);
+ } else {
+ return FALSE;
+ }
+ } else if (eq != GST_VALUE_EQUAL) {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * gst_structure_can_intersect:
+ * @struct1: a #GstStructure
+ * @struct2: a #GstStructure
+ *
+ * Tries interesecting @struct1 and @struct2 and reports whether the result
+ * would not be empty.
+ *
+ * Returns: %TRUE if intersection would not be empty
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_structure_can_intersect (const GstStructure * struct1,
+ const GstStructure * struct2)
+{
+ g_return_val_if_fail (GST_IS_STRUCTURE (struct1), FALSE);
+ g_return_val_if_fail (GST_IS_STRUCTURE (struct2), FALSE);
+
+ if (G_UNLIKELY (struct1->name != struct2->name))
+ return FALSE;
+
+ /* tries to intersect if we have the field in both */
+ if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
+ gst_caps_structure_can_intersect_field, (gpointer) struct2)))
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+gst_caps_structure_is_subset_field (GQuark field_id, const GValue * value,
+ gpointer user_data)
+{
+ GstStructure *superset = user_data;
+ GValue subtraction = { 0, };
+ const GValue *other;
+
+ if (!(other = gst_structure_id_get_value (superset, field_id)))
+ /* field is missing in the superset => is subset */
+ return TRUE;
+
+ /* equal values are subset */
+ if (gst_value_compare (other, value) == GST_VALUE_EQUAL)
+ return TRUE;
+
+ /*
+ * 1 - [1,2] = empty
+ * -> !subset
+ *
+ * [1,2] - 1 = 2
+ * -> 1 - [1,2] = empty
+ * -> subset
+ *
+ * [1,3] - [1,2] = 3
+ * -> [1,2] - [1,3] = empty
+ * -> subset
+ *
+ * {1,2} - {1,3} = 2
+ * -> {1,3} - {1,2} = 3
+ * -> !subset
+ *
+ * First caps subtraction needs to return a non-empty set, second
+ * subtractions needs to give en empty set.
+ */
+ if (gst_value_subtract (&subtraction, other, value)) {
+ g_value_unset (&subtraction);
+ /* !empty result, swapping must be empty */
+ if (!gst_value_subtract (&subtraction, value, other))
+ return TRUE;
+
+ g_value_unset (&subtraction);
+ }
+ return FALSE;
+}
+
+/**
+ * gst_structure_is_subset:
+ * @subset: a #GstStructure
+ * @superset: a potentially greater #GstStructure
+ *
+ * Checks if @subset is a subset of @superset, i.e. has the same
+ * structure name and for all fields that are existing in @superset,
+ * @subset has a value that is a subset of the value in @superset.
+ *
+ * Returns: %TRUE if @subset is a subset of @superset
+ *
+ * Since: 0.10.35
+ */
+gboolean
+gst_structure_is_subset (const GstStructure * subset,
+ const GstStructure * superset)
+{
+ if ((superset->name != subset->name) ||
+ (gst_structure_n_fields (superset) > gst_structure_n_fields (subset)))
+ return FALSE;
+
+ return gst_structure_foreach ((GstStructure *) subset,
+ gst_caps_structure_is_subset_field, (gpointer) superset);
+}
diff --git a/gst/gststructure.h b/gst/gststructure.h
index 57e34c0f714c7229ea7c1527e6bdee6a431c18ec..6e020fce33886d3b704446a4e7be7b8fd9421726 100644 (file)
--- a/gst/gststructure.h
+++ b/gst/gststructure.h
const gint target_numerator,
const gint target_denominator);
+gboolean gst_structure_is_equal(const GstStructure *structure1,
+ const GstStructure *structure2);
+gboolean gst_structure_is_subset(const GstStructure *subset,
+ const GstStructure *superset);
+gboolean gst_structure_can_intersect(const GstStructure *struct1,
+ const GstStructure *struct2);
+GstStructure* gst_structure_intersect (const GstStructure *struct1,
+ const GstStructure *struct2);
+
G_END_DECLS
#endif
diff --git a/gst/gstsystemclock.c b/gst/gstsystemclock.c
index 7ada0c952bba9a69b7a5c155b362f3edee6785cf..938704e544cb8f24f9609c57e18dc24ed3b581ef 100644 (file)
--- a/gst/gstsystemclock.c
+++ b/gst/gstsystemclock.c
if (sysclock->priv->wakeup_count == 0) {
GST_CAT_DEBUG (GST_CAT_CLOCK, "writing control");
while (!gst_poll_write_control (sysclock->priv->timer)) {
- g_warning
- ("gstsystemclock: write control failed in wakeup_async, trying again : %d:%s\n",
- errno, g_strerror (errno));
+ if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+ g_warning
+ ("gstsystemclock: write control failed in wakeup_async, trying again: %d:%s\n",
+ errno, g_strerror (errno));
+ } else {
+ g_critical
+ ("gstsystemclock: write control failed in wakeup_async: %d:%s\n",
+ errno, g_strerror (errno));
+ return;
+ }
}
}
sysclock->priv->wakeup_count++;
diff --git a/gst/gsttaglist.c b/gst/gsttaglist.c
index 7022b26ab11e563a989214c7be689bf94de3f2c5..385e3b019811340330eaafa24c298e691082edad 100644 (file)
--- a/gst/gsttaglist.c
+++ b/gst/gsttaglist.c
g_warning ("unknown tag '%s'", tag);
return;
}
-#if GLIB_CHECK_VERSION(2,23,3)
G_VALUE_COLLECT_INIT (&value, info->type, var_args, 0, &error);
-#else
- g_value_init (&value, info->type);
- G_VALUE_COLLECT (&value, var_args, 0, &error);
-#endif
if (error) {
g_warning ("%s: %s", G_STRLOC, error);
g_free (error);
diff --git a/gst/gstvalue.c b/gst/gstvalue.c
index 8baf1e6150734ff041e50fb371b6b174343299cb..381716094120d92db051f1017fbd21406ecdbbdf 100644 (file)
--- a/gst/gstvalue.c
+++ b/gst/gstvalue.c
gst_value_compare (const GValue * value1, const GValue * value2)
{
GstValueCompareFunc compare;
+ GType ltype;
g_return_val_if_fail (G_IS_VALUE (value1), GST_VALUE_LESS_THAN);
g_return_val_if_fail (G_IS_VALUE (value2), GST_VALUE_GREATER_THAN);
+ /* Special case: lists and scalar values
+ * "{ 1 }" and "1" are equal */
+ ltype = gst_value_list_get_type ();
+ if (G_VALUE_HOLDS (value1, ltype) && !G_VALUE_HOLDS (value2, ltype)
+ && gst_value_list_get_size (value1) == 1) {
+ const GValue *elt;
+
+ elt = gst_value_list_get_value (value1, 0);
+ return gst_value_compare (elt, value2);
+ } else if (G_VALUE_HOLDS (value2, ltype) && !G_VALUE_HOLDS (value1, ltype)
+ && gst_value_list_get_size (value2) == 1) {
+ const GValue *elt;
+
+ elt = gst_value_list_get_value (value2, 0);
+ return gst_value_compare (elt, value1);
+ }
+
if (G_VALUE_TYPE (value1) != G_VALUE_TYPE (value2))
return GST_VALUE_UNORDERED;
diff --git a/gst/parse/Makefile.am b/gst/parse/Makefile.am
index 7e834048f2c6363872c13a9446540599fe013125..30abeb3715f205348b9e1d6a677a4f7585290c47 100644 (file)
--- a/gst/parse/Makefile.am
+++ b/gst/parse/Makefile.am
echo '#ifdef HAVE_CONFIG_H' > lex._gst_parse_yy_tmp2.c && \
echo '#include <config.h>' >> lex._gst_parse_yy_tmp2.c && \
echo '#endif' >> lex._gst_parse_yy_tmp2.c && \
+ echo 'static inline int _gst_parse_yyget_column (void * yyscanner);' >> lex._gst_parse_yy_tmp2.c && \
+ echo 'static inline void _gst_parse_yyset_column (int column_no , void * yyscanner);' >> lex._gst_parse_yy_tmp2.c && \
cat lex._gst_parse_yy_tmp.c >> lex._gst_parse_yy_tmp2.c && \
rm lex._gst_parse_yy_tmp.c && \
mv lex._gst_parse_yy_tmp2.c lex._gst_parse_yy.c
diff --git a/gst/parse/types.h b/gst/parse/types.h
index 7e8b9944552b0ec4c0460da49062dab27a300eab..db1f585646c5e4e81e4b0b16f2257c61a23dfee9 100644 (file)
--- a/gst/parse/types.h
+++ b/gst/parse/types.h
gst_parse_unescape (gchar *str)
{
gchar *walk;
+ gboolean in_quotes;
g_return_if_fail (str != NULL);
walk = str;
+ in_quotes = FALSE;
while (*walk) {
- if (*walk == '\\') {
+ if (*walk == '\\' && !in_quotes) {
walk++;
/* make sure we don't read beyond the end of the string */
if (*walk == '\0')
break;
+ } else if (*walk == '"' && (!in_quotes || (in_quotes
+ && (*(walk - 1) != '\\')))) {
+ /* don't unescape inside quotes and don't switch
+ * state with escaped quoted inside quotes */
+ in_quotes = !in_quotes;
}
*str = *walk;
str++;
index e80c8f4baf2f558b8d1af5ad6faecb312ac3b7e9..e0158ce119f955ed9aaf4f04c8398007577ecdd8 100644 (file)
* contain a valid frame, this call must return FALSE and optionally
* set the @skipsize value to inform base class that how many bytes
* it needs to skip in order to find a valid frame. @framesize can always
- * indicate a new minimum for current frame parsing. The passed buffer
+ * indicate a new minimum for current frame parsing. Indicating G_MAXUINT
+ * for requested amount means subclass simply needs best available
+ * subsequent data. In push mode this amounts to an additional input buffer
+ * (thus minimal additional latency), in pull mode this amounts to some
+ * arbitrary reasonable buffer size increase. The passed buffer
* is read-only. Note that @check_valid_frame might receive any small
* amount of input data when leftover data is being drained (e.g. at EOS).
* </para></listitem>
guint bitrate;
guint lead_in, lead_out;
GstClockTime lead_in_ts, lead_out_ts;
+ GstClockTime min_latency, max_latency;
gboolean discont;
gboolean flushing;
/* Segment event that closes the running segment prior to SEEK */
GstEvent *close_segment;
+
+ /* push mode helper frame */
+ GstBaseParseFrame frame;
};
typedef struct _GstBaseParseSeek
frame->buffer = NULL;
}
- if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC))
+ if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) {
g_slice_free (GstBaseParseFrame, frame);
+ } else {
+ memset (frame, 0, sizeof (*frame));
+ }
}
GType
g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL);
g_slist_free (parse->priv->pending_seeks);
parse->priv->pending_seeks = NULL;
+
+ /* we know it is not alloc'ed, but maybe other stuff to free, some day ... */
+ parse->priv->frame._private_flags |=
+ GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
+ gst_base_parse_frame_free (&parse->priv->frame);
GST_OBJECT_UNLOCK (parse);
}
parse->priv->flushing = FALSE;
parse->priv->discont = TRUE;
parse->priv->last_ts = GST_CLOCK_TIME_NONE;
+ parse->priv->frame._private_flags |=
+ GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
+ gst_base_parse_frame_free (&parse->priv->frame);
break;
case GST_EVENT_EOS:
const guint8 *data;
guint old_min_size = 0, min_size, av;
GstClockTime timestamp;
- GstBaseParseFrame _frame;
GstBaseParseFrame *frame;
parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
bclass = GST_BASE_PARSE_GET_CLASS (parse);
- frame = &_frame;
-
- gst_base_parse_frame_init (frame);
+ frame = &parse->priv->frame;
if (G_LIKELY (buffer)) {
GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
if (G_UNLIKELY (parse->priv->passthrough)) {
+ gst_base_parse_frame_init (frame);
frame->buffer = gst_buffer_make_metadata_writable (buffer);
return gst_base_parse_push_frame (parse, frame);
}
gst_adapter_push (parse->priv->adapter, buffer);
}
+ if (G_UNLIKELY (buffer &&
+ GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
+ frame->_private_flags |= GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
+ gst_base_parse_frame_free (frame);
+ }
+
/* Parse and push as many frames as possible */
/* Stop either when adapter is empty or we are flushing */
while (!parse->priv->flushing) {
gboolean res;
+ /* maintain frame state for a single frame parsing round across _chain calls,
+ * so only init when needed */
+ if (!frame->_private_flags)
+ gst_base_parse_frame_init (frame);
+
tmpbuf = gst_buffer_new ();
old_min_size = 0;
/* Synchronization loop */
for (;;) {
+ /* note: if subclass indicates MAX fsize,
+ * this will not likely be available anyway ... */
min_size = MAX (parse->priv->min_frame_size, fsize);
av = gst_adapter_available (parse->priv->adapter);
/* always pass all available data */
data = gst_adapter_peek (parse->priv->adapter, av);
GST_BUFFER_DATA (tmpbuf) = (guint8 *) data;
- GST_BUFFER_SIZE (tmpbuf) = min_size;
+ GST_BUFFER_SIZE (tmpbuf) = av;
GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset;
GST_BUFFER_FLAG_SET (tmpbuf, GST_MINI_OBJECT_FLAG_READONLY);
GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
" (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
+ /* let's make this efficient for all subclass once and for all;
+ * maybe it does not need this much, but in the latter case, we know we are
+ * in pull mode here and might as well try to read and supply more anyway
+ * (so does the buffer caching mechanism) */
+ fsize = 64 * 1024;
+
while (TRUE) {
gboolean res;
if (!parse->priv->discont)
parse->priv->sync_offset = parse->priv->offset;
parse->priv->discont = TRUE;
- /* something changed least; nullify loop check */
+ /* something changed at least; nullify loop check */
+ if (fsize == G_MAXUINT)
+ fsize = old_min_size + 64 * 1024;
old_min_size = 0;
}
/* skip == 0 should imply subclass set min_size to need more data;
GST_INFO_OBJECT (parse, "passthrough: %s", (passthrough) ? "yes" : "no");
}
+/**
+ * gst_base_parse_set_latency:
+ * @parse: a #GstBaseParse
+ * @min_latency: minimum parse latency
+ * @max_latency: maximum parse latency
+ *
+ * Sets the minimum and maximum (which may likely be equal) latency introduced
+ * by the parsing process. If there is such a latency, which depends on the
+ * particular parsing of the format, it typically corresponds to 1 frame duration.
+ *
+ * Since: 0.10.34
+ */
+void
+gst_base_parse_set_latency (GstBaseParse * parse, GstClockTime min_latency,
+ GstClockTime max_latency)
+{
+ GST_OBJECT_LOCK (parse);
+ parse->priv->min_latency = min_latency;
+ parse->priv->max_latency = max_latency;
+ GST_OBJECT_UNLOCK (parse);
+ GST_INFO_OBJECT (parse, "min/max latency %" GST_TIME_FORMAT ", %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (min_latency),
+ GST_TIME_ARGS (max_latency));
+}
+
static gboolean
gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
GstClockTime * duration)
}
break;
}
+ case GST_QUERY_LATENCY:
+ {
+ if ((res = gst_pad_peer_query (parse->sinkpad, query))) {
+ gboolean live;
+ GstClockTime min_latency, max_latency;
+
+ gst_query_parse_latency (query, &live, &min_latency, &max_latency);
+ GST_DEBUG_OBJECT (parse, "Peer latency: live %d, min %"
+ GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
+ GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency));
+
+ GST_OBJECT_LOCK (parse);
+ /* add our latency */
+ if (min_latency != -1)
+ min_latency += parse->priv->min_latency;
+ if (max_latency != -1)
+ max_latency += parse->priv->max_latency;
+ GST_OBJECT_UNLOCK (parse);
+
+ gst_query_set_latency (query, live, min_latency, max_latency);
+ }
+ break;
+ }
default:
res = gst_pad_query_default (pad, query);
break;
index 74eaa97b84c5fb3c594e66dbc7a7ee75d2cb6cb4..655ad0e4a31866034eade72749e38452721b60f6 100644 (file)
guint lead_in,
guint lead_out);
+void gst_base_parse_set_latency (GstBaseParse * parse,
+ GstClockTime min_latency,
+ GstClockTime max_latency);
+
gboolean gst_base_parse_convert_default (GstBaseParse * parse,
GstFormat src_format,
gint64 src_value,
index 7740a77e95b42a57b712e5823afced56b512ce6a..d60ba6fdfd6b1560497de9c658ccadd760a1c462 100644 (file)
time += base_time;
/* Re-use existing clockid if available */
- if (G_LIKELY (sink->priv->cached_clock_id != NULL)) {
+ /* FIXME: Casting to GstClockEntry only works because the types
+ * are the same */
+ if (G_LIKELY (sink->priv->cached_clock_id != NULL
+ && GST_CLOCK_ENTRY_CLOCK ((GstClockEntry *) sink->
+ priv->cached_clock_id) == clock)) {
if (!gst_clock_single_shot_id_reinit (clock, sink->priv->cached_clock_id,
time)) {
gst_clock_id_unref (sink->priv->cached_clock_id);
sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time);
}
- } else
+ } else {
+ if (sink->priv->cached_clock_id != NULL)
+ gst_clock_id_unref (sink->priv->cached_clock_id);
sink->priv->cached_clock_id = gst_clock_new_single_shot_id (clock, time);
+ }
GST_OBJECT_UNLOCK (sink);
/* A blocking wait is performed on the clock. We save the ClockID
*
* Queue an object for rendering.
* The first prerollable object queued will complete the preroll. If the
- * preroll queue if filled, we render all the objects in the queue.
+ * preroll queue is filled, we render all the objects in the queue.
*
* This function takes ownership of the object.
*/
index 59319e256731bdccb663c0cc0b01d6e822fbc7b2..947562c7ad849a52bed181d718155e554b22b87d 100644 (file)
GstClockTimeDiff ts_offset;
gboolean do_timestamp;
+ volatile gint dynamic_size;
/* stream sequence number */
guint32 seqnum;
static GstFlowReturn gst_base_src_get_range (GstBaseSrc * src, guint64 offset,
guint length, GstBuffer ** buf);
static gboolean gst_base_src_seekable (GstBaseSrc * src);
+static gboolean gst_base_src_update_length (GstBaseSrc * src, guint64 offset,
+ guint * length);
static void
gst_base_src_base_init (gpointer g_class)
GST_OBJECT_UNLOCK (src);
}
+/**
+ * gst_base_src_set_dynamic_size:
+ * @src: base source instance
+ * @dynamic: new dynamic size mode
+ *
+ * If not @dynamic, size is only updated when needed, such as when trying to
+ * read past current tracked size. Otherwise, size is checked for upon each
+ * read.
+ *
+ * Since: 0.10.35
+ */
+void
+gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic)
+{
+ g_return_if_fail (GST_IS_BASE_SRC (src));
+
+ g_atomic_int_set (&src->priv->dynamic_size, dynamic);
+}
+
/**
* gst_base_src_query_latency:
* @src: the source
{
gint64 duration;
GstFormat seg_format;
+ guint length = 0;
+
+ /* may have to refresh duration */
+ if (g_atomic_int_get (&src->priv->dynamic_size))
+ gst_base_src_update_length (src, 0, &length);
- GST_OBJECT_LOCK (src);
/* this is the duration as configured by the subclass. */
+ GST_OBJECT_LOCK (src);
duration = src->segment.duration;
seg_format = src->segment.format;
GST_OBJECT_UNLOCK (src);
GstBaseSrcClass *bclass;
GstFormat format;
gint64 stop;
+ gboolean dynamic;
bclass = GST_BASE_SRC_GET_CLASS (src);
@@ -2052,11 +2080,14 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length)
", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
*length, size, stop, maxsize);
+ dynamic = g_atomic_int_get (&src->priv->dynamic_size);
+ GST_DEBUG_OBJECT (src, "dynamic size: %d", dynamic);
+
/* check size if we have one */
if (maxsize != -1) {
/* if we run past the end, check if the file became bigger and
* retry. */
- if (G_UNLIKELY (offset + *length >= maxsize)) {
+ if (G_UNLIKELY (offset + *length >= maxsize || dynamic)) {
/* see if length of the file changed */
if (bclass->get_size)
if (!bclass->get_size (src, &size))
index 2a3caecdbba044fed0693dbfd34c6f9a898db2ad..87e1c06f413e7f1c528c9c4110c5e30769e77d94 100644 (file)
void gst_base_src_set_format (GstBaseSrc *src, GstFormat format);
+void gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic);
+
gboolean gst_base_src_query_latency (GstBaseSrc *src, gboolean * live,
GstClockTime * min_latency,
GstClockTime * max_latency);
index ccf0802c24a42b7f39f5f46d98935c6545afcb8f..a46642ea24cf3d97ad970aa803f42c837f89d9a0 100644 (file)
{
GstBaseTransform *trans;
GstPad *otherpad;
- GstCaps *caps;
+ GstCaps *peercaps, *caps;
trans = GST_BASE_TRANSFORM (gst_pad_get_parent (pad));
otherpad = (pad == trans->srcpad) ? trans->sinkpad : trans->srcpad;
/* we can do what the peer can */
- caps = gst_pad_peer_get_caps_reffed (otherpad);
- if (caps) {
+ peercaps = gst_pad_peer_get_caps_reffed (otherpad);
+ if (peercaps) {
GstCaps *temp;
const GstCaps *templ;
- GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, caps);
+ GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, peercaps);
/* filtered against our padtemplate on the other side */
templ = gst_pad_get_pad_template_caps (otherpad);
GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ);
- temp = gst_caps_intersect (caps, templ);
+ temp = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
- gst_caps_unref (caps);
/* then see what we can transform this to */
caps = gst_base_transform_transform_caps (trans,
temp = gst_caps_intersect_full (caps, templ, GST_CAPS_INTERSECT_FIRST);
GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp);
gst_caps_unref (caps);
- /* this is what we can do */
caps = temp;
+
+ /* Now try if we can put the untransformed downstream caps first */
+ temp = gst_caps_intersect_full (peercaps, caps, GST_CAPS_INTERSECT_FIRST);
+ if (!gst_caps_is_empty (temp)) {
+ gst_caps_merge (temp, caps);
+ caps = temp;
+ } else {
+ gst_caps_unref (temp);
+ }
} else {
/* no peer or the peer can do anything, our padtemplate is enough then */
caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
done:
GST_DEBUG_OBJECT (trans, "returning %" GST_PTR_FORMAT, caps);
+ if (peercaps)
+ gst_caps_unref (peercaps);
+
gst_object_unref (trans);
return caps;
GST_DEBUG_OBJECT (trans,
"intersecting against padtemplate %" GST_PTR_FORMAT, templ_caps);
- intersect = gst_caps_intersect (othercaps, templ_caps);
+ intersect =
+ gst_caps_intersect_full (othercaps, templ_caps,
+ GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (othercaps);
othercaps = intersect;
if (peercaps) {
GstCaps *intersect;
- intersect = gst_caps_intersect (peercaps, sink_suggest);
+ intersect =
+ gst_caps_intersect_full (sink_suggest, peercaps,
+ GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (peercaps);
gst_caps_unref (sink_suggest);
sink_suggest = intersect;
GST_DEBUG_OBJECT (trans, "Checking if the input caps is compatible "
"with the non-fixed caps suggestion");
- intersect = gst_caps_intersect (sink_suggest, caps);
+ intersect =
+ gst_caps_intersect_full (sink_suggest, caps,
+ GST_CAPS_INTERSECT_FIRST);
if (!gst_caps_is_empty (intersect)) {
GST_DEBUG_OBJECT (trans, "It is, using it");
gst_caps_replace (&sink_suggest, caps);
index b746371722c29f8af5f53b42e2ab4f56883635c7..004eb7457d758a60eb28f71cf68e01c27b8d514f 100644 (file)
*/
#define assert_equals_int(a, b) fail_unless_equals_int(a, b)
+/**
+ * fail_unless_equals_int64:
+ * @a: a #gint64 value or expression
+ * @b: a #gint64 value or expression
+ *
+ * This macro checks that @a and @b are equal and aborts if this is not the
+ * case, printing both expressions and the values they evaluated to. This
+ * macro is for use in unit tests.
+ */
+#define fail_unless_equals_int64(a, b) \
+G_STMT_START { \
+ gint64 first = a; \
+ gint64 second = b; \
+ fail_unless(first == second, \
+ "'" #a "' (%" G_GINT64_FORMAT") is not equal to '" #b"' (%" \
+ G_GINT64_FORMAT")", first, second); \
+} G_STMT_END;
+/**
+ * assert_equals_int64:
+ * @a: a #gint64 value or expression
+ * @b: a #gint64 value or expression
+ *
+ * This macro checks that @a and @b are equal and aborts if this is not the
+ * case, printing both expressions and the values they evaluated to. This
+ * macro is for use in unit tests.
+ */
+#define assert_equals_int64(a, b) fail_unless_equals_int64(a, b)
+
/**
* fail_unless_equals_uint64:
* @a: a #guint64 value or expression
index 6d7f0f9cea6d64bc7ce8fc6a7cf16f1509768770..3d38c6c59dedb1af48276e1ccb18fbd50e252138 100644 (file)
GST_INFO_OBJECT (src, "marking fd %d as seekable", src->fd);
src->seekable_fd = TRUE;
+
+ gst_base_src_set_dynamic_size (GST_BASE_SRC (src), TRUE);
}
return;
{
GST_INFO_OBJECT (src, "marking fd %d as NOT seekable", src->fd);
src->seekable_fd = FALSE;
+ gst_base_src_set_dynamic_size (GST_BASE_SRC (src), FALSE);
}
}
index cc07a72a0210baf94adccb2200981d7942234c95..f8dbfe2c4c0805111514748d3f1020041dd83ba7 100644 (file)
* don't know their length, so seeking isn't useful/meaningful */
src->seekable = src->seekable && src->is_regular;
+ gst_base_src_set_dynamic_size (basesrc, src->seekable);
+
return TRUE;
/* ERROR */
index 32a4aa9a060f6e1dd7abd5d0f112936a0917a842..f62a488c66380e7829034c8fd8cac2dec05ae8c4 100644 (file)
{
PROP_0,
PROP_N_PADS,
- PROP_ACTIVE_PAD
+ PROP_ACTIVE_PAD,
+ PROP_SYNC_STREAMS
};
+#define DEFAULT_SYNC_STREAMS FALSE
+
#define DEFAULT_PAD_ALWAYS_OK TRUE
enum
return self->flushing;
}
+/* must be called with the SELECTOR_LOCK, will block until the running time
+ * of the active pad is after this pad or return TRUE when flushing */
+static gboolean
+gst_input_selector_wait_running_time (GstInputSelector * sel,
+ GstSelectorPad * pad, GstBuffer * buf)
+{
+ GstPad *active_sinkpad;
+ GstSelectorPad *active_selpad;
+ GstSegment *seg, *active_seg;
+ GstClockTime running_time, active_running_time = -1;
+
+ seg = &pad->segment;
+
+ active_sinkpad =
+ gst_input_selector_activate_sinkpad (sel, GST_PAD_CAST (pad));
+ active_selpad = GST_SELECTOR_PAD_CAST (active_sinkpad);
+ active_seg = &active_selpad->segment;
+
+ /* We can only sync if the segments are in time format or
+ * if the active pad had no newsegment event yet */
+ if (seg->format != GST_FORMAT_TIME ||
+ (active_seg->format != GST_FORMAT_TIME
+ && active_seg->format != GST_FORMAT_UNDEFINED))
+ return FALSE;
+
+ /* If we have no valid timestamp we can't sync this buffer */
+ if (!GST_BUFFER_TIMESTAMP_IS_VALID (buf))
+ return FALSE;
+
+ running_time = GST_BUFFER_TIMESTAMP (buf);
+ /* If possible try to get the running time at the end of the buffer */
+ if (GST_BUFFER_DURATION_IS_VALID (buf))
+ running_time += GST_BUFFER_DURATION (buf);
+ if (running_time > seg->stop)
+ running_time = seg->stop;
+ running_time =
+ gst_segment_to_running_time (seg, GST_FORMAT_TIME, running_time);
+ /* If this is outside the segment don't sync */
+ if (running_time == -1)
+ return FALSE;
+
+ /* Get active pad's running time, if no configured segment yet keep at -1 */
+ if (active_seg->format == GST_FORMAT_TIME)
+ active_running_time =
+ gst_segment_to_running_time (active_seg, GST_FORMAT_TIME,
+ active_seg->last_stop);
+
+ /* Wait until
+ * a) this is the active pad
+ * b) the pad or the selector is flushing
+ * c) the selector is not blocked
+ * d) the active pad has no running time or the active
+ * pad's running time is before this running time
+ * e) the active pad has a non-time segment
+ */
+ while (pad != active_selpad && !sel->flushing && !pad->flushing &&
+ (sel->blocked || active_running_time == -1
+ || running_time >= active_running_time)) {
+ if (!sel->blocked)
+ GST_DEBUG_OBJECT (pad,
+ "Waiting for active streams to advance. %" GST_TIME_FORMAT " >= %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (running_time),
+ GST_TIME_ARGS (active_running_time));
+
+ GST_INPUT_SELECTOR_WAIT (sel);
+
+ /* Get new active pad, it might have changed */
+ active_sinkpad =
+ gst_input_selector_activate_sinkpad (sel, GST_PAD_CAST (pad));
+ active_selpad = GST_SELECTOR_PAD_CAST (active_sinkpad);
+ active_seg = &active_selpad->segment;
+
+ /* If the active segment is configured but not to time format
+ * we can't do any syncing at all */
+ if (active_seg->format != GST_FORMAT_TIME
+ && active_seg->format != GST_FORMAT_UNDEFINED)
+ break;
+
+ /* Get the new active pad running time */
+ if (active_seg->format == GST_FORMAT_TIME)
+ active_running_time =
+ gst_segment_to_running_time (active_seg, GST_FORMAT_TIME,
+ active_seg->last_stop);
+ else
+ active_running_time = -1;
+
+ if (!sel->blocked)
+ GST_DEBUG_OBJECT (pad,
+ "Waited for active streams to advance. %" GST_TIME_FORMAT " >= %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (running_time),
+ GST_TIME_ARGS (active_running_time));
+
+ }
+
+ /* Return TRUE if the selector or the pad is flushing */
+ return (sel->flushing || pad->flushing);
+}
+
+
static GstFlowReturn
gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
{
prev_active_sinkpad = sel->active_sinkpad;
active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
+ /* In sync mode wait until the active pad has advanced
+ * after the running time of the current buffer */
+ if (sel->sync_streams && active_sinkpad != pad) {
+ if (gst_input_selector_wait_running_time (sel, selpad, buf))
+ goto flushing;
+ }
+
+ /* Might have changed while waiting */
+ active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
+
/* update the segment on the srcpad */
start_time = GST_BUFFER_TIMESTAMP (buf);
if (GST_CLOCK_TIME_IS_VALID (start_time)) {
if (pad != active_sinkpad)
goto ignore;
+ /* Tell all non-active pads that we advanced the running time */
+ if (sel->sync_streams)
+ GST_INPUT_SELECTOR_BROADCAST (sel);
+
if (G_UNLIKELY (sel->pending_close)) {
GstSegment *cseg = &sel->segment;
"The currently active sink pad", GST_TYPE_PAD,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstInputSelector:sync-streams
+ *
+ * If set to %TRUE all inactive streams will be synced to the
+ * running time of the active stream. This makes sure that no
+ * buffers are dropped by input-selector that might be needed
+ * when switching the active pad.
+ *
+ * Since: 0.10.35
+ */
+ g_object_class_install_property (gobject_class, PROP_SYNC_STREAMS,
+ g_param_spec_boolean ("sync-streams", "Sync Streams",
+ "Synchronize inactive streams to the running time of the active stream",
+ DEFAULT_SYNC_STREAMS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
/**
* GstInputSelector::block:
* @inputselector: the #GstInputSelector
sel->active_sinkpad = NULL;
sel->padcount = 0;
gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED);
+ sel->sync_streams = DEFAULT_SYNC_STREAMS;
sel->lock = g_mutex_new ();
sel->cond = g_cond_new ();
active_pad_p = &self->active_sinkpad;
gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad));
+
+ /* Wake up all non-active pads in sync mode, they might be
+ * the active pad now */
+ if (self->sync_streams)
+ GST_INPUT_SELECTOR_BROADCAST (self);
+
GST_DEBUG_OBJECT (self, "New active pad is %" GST_PTR_FORMAT,
self->active_sinkpad);
GST_INPUT_SELECTOR_UNLOCK (sel);
break;
}
+ case PROP_SYNC_STREAMS:
+ {
+ GST_INPUT_SELECTOR_LOCK (sel);
+ sel->sync_streams = g_value_get_boolean (value);
+ GST_INPUT_SELECTOR_UNLOCK (sel);
+ break;
+ }
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
g_value_set_object (value, sel->active_sinkpad);
GST_INPUT_SELECTOR_UNLOCK (object);
break;
+ case PROP_SYNC_STREAMS:
+ GST_INPUT_SELECTOR_LOCK (object);
+ g_value_set_boolean (value, sel->sync_streams);
+ GST_INPUT_SELECTOR_UNLOCK (object);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
index 0ed7a4b3cb1c079b997942667dff6f3faa9ac421..f370999689e388b4c2c67fc07a375797154d8ae9 100644 (file)
GstPad *active_sinkpad;
guint n_pads;
guint padcount;
+ gboolean sync_streams;
GstSegment segment; /* the output segment */
gboolean pending_close; /* if we should push a close first */
index 541e04235f9d8475573c258a8554c0aed1672dc3..9f39155afcc0abe1455c82670f7e43c4bb60baf1 100644 (file)
guint32 nextid; /* ID of the next object waiting to be pushed */
guint32 oldid; /* ID of the last object pushed (last in a series) */
guint32 last_oldid; /* Previously observed old_id, reset to MAXUINT32 on flush */
+ GstClockTime next_time; /* End running time of next buffer to be pushed */
+ GstClockTime last_time; /* Start running time of last pushed buffer */
GCond *turn; /* SingleQueue turn waiting conditional */
};
static void wake_up_next_non_linked (GstMultiQueue * mq);
static void compute_high_id (GstMultiQueue * mq);
+static void compute_high_time (GstMultiQueue * mq);
static void single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq);
static void single_queue_underrun_cb (GstDataQueue * dq, GstSingleQueue * sq);
#define DEFAULT_USE_BUFFERING FALSE
#define DEFAULT_LOW_PERCENT 10
#define DEFAULT_HIGH_PERCENT 99
+#define DEFAULT_SYNC_BY_RUNNING_TIME FALSE
enum
{
PROP_USE_BUFFERING,
PROP_LOW_PERCENT,
PROP_HIGH_PERCENT,
+ PROP_SYNC_BY_RUNNING_TIME,
PROP_LAST
};
"High threshold for buffering to finish", 0, 100,
DEFAULT_HIGH_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ /**
+ * GstMultiQueue:sync-by-running-time
+ *
+ * If enabled multiqueue will synchronize deactivated or not-linked streams
+ * to the activated and linked streams by taking the running time.
+ * Otherwise multiqueue will synchronize the deactivated or not-linked
+ * streams by keeping the order in which buffers and events arrived compared
+ * to active and linked streams.
+ *
+ * Since: 0.10.35
+ */
+ g_object_class_install_property (gobject_class, PROP_SYNC_BY_RUNNING_TIME,
+ g_param_spec_boolean ("sync-by-running-time", "Sync By Running Time",
+ "Synchronize deactivated or not-linked streams by running time",
+ DEFAULT_SYNC_BY_RUNNING_TIME,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gobject_class->finalize = gst_multi_queue_finalize;
mqueue->low_percent = DEFAULT_LOW_PERCENT;
mqueue->high_percent = DEFAULT_HIGH_PERCENT;
+ mqueue->sync_by_running_time = DEFAULT_SYNC_BY_RUNNING_TIME;
+
mqueue->counter = 1;
mqueue->highid = -1;
+ mqueue->high_time = GST_CLOCK_TIME_NONE;
mqueue->qlock = g_mutex_new ();
}
case PROP_HIGH_PERCENT:
mq->high_percent = g_value_get_int (value);
break;
+ case PROP_SYNC_BY_RUNNING_TIME:
+ mq->sync_by_running_time = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_HIGH_PERCENT:
g_value_set_int (value, mq->high_percent);
break;
+ case PROP_SYNC_BY_RUNNING_TIME:
+ g_value_set_boolean (value, mq->sync_by_running_time);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -741,8 +771,15 @@ gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush)
sq->nextid = 0;
sq->oldid = 0;
sq->last_oldid = G_MAXUINT32;
+ sq->next_time = GST_CLOCK_TIME_NONE;
+ sq->last_time = GST_CLOCK_TIME_NONE;
gst_data_queue_set_flushing (sq->queue, FALSE);
+ /* Reset high time to be recomputed next */
+ GST_MULTI_QUEUE_MUTEX_LOCK (mq);
+ mq->high_time = GST_CLOCK_TIME_NONE;
+ GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
+
sq->flushing = FALSE;
GST_LOG_OBJECT (mq, "SingleQueue %d : starting task", sq->id);
GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
}
+static GstClockTime
+get_running_time (GstSegment * segment, GstMiniObject * object, gboolean end)
+{
+ GstClockTime time = GST_CLOCK_TIME_NONE;
+
+ if (GST_IS_BUFFER (object)) {
+ GstBuffer *buf = GST_BUFFER_CAST (object);
+
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+ time = GST_BUFFER_TIMESTAMP (buf);
+ if (end && GST_BUFFER_DURATION_IS_VALID (buf))
+ time += GST_BUFFER_DURATION (buf);
+ if (time > segment->stop)
+ time = segment->stop;
+ time = gst_segment_to_running_time (segment, GST_FORMAT_TIME, time);
+ }
+ } else if (GST_IS_BUFFER_LIST (object)) {
+ GstBufferList *list = GST_BUFFER_LIST_CAST (object);
+ GstBufferListIterator *it = gst_buffer_list_iterate (list);
+ GstBuffer *buf;
+
+ do {
+ while ((buf = gst_buffer_list_iterator_next (it))) {
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
+ time = GST_BUFFER_TIMESTAMP (buf);
+ if (end && GST_BUFFER_DURATION_IS_VALID (buf))
+ time += GST_BUFFER_DURATION (buf);
+ if (time > segment->stop)
+ time = segment->stop;
+ time = gst_segment_to_running_time (segment, GST_FORMAT_TIME, time);
+ if (!end)
+ goto done;
+ } else if (!end) {
+ goto done;
+ }
+ }
+ } while (gst_buffer_list_iterator_next_group (it));
+ } else if (GST_IS_EVENT (object)) {
+ GstEvent *event = GST_EVENT_CAST (object);
+
+ /* For newsegment events return the running time of the start position */
+ if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
+ GstSegment new_segment = *segment;
+ gboolean update;
+ gdouble rate, applied_rate;
+ GstFormat format;
+ gint64 start, stop, position;
+
+ gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
+ &format, &start, &stop, &position);
+ if (format == GST_FORMAT_TIME) {
+ gst_segment_set_newsegment_full (&new_segment, update, rate,
+ applied_rate, format, start, stop, position);
+
+ time =
+ gst_segment_to_running_time (&new_segment, GST_FORMAT_TIME,
+ new_segment.start);
+ }
+ }
+ }
+
+done:
+ return time;
+}
+
static GstFlowReturn
gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
GstMiniObject * object)
GstMiniObject *object = NULL;
guint32 newid;
GstFlowReturn result;
+ GstClockTime next_time;
sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
mq = sq->mqueue;
object = gst_multi_queue_item_steal_object (item);
gst_multi_queue_item_destroy (item);
+ /* Get running time of the item. Events will have GST_CLOCK_TIME_NONE */
+ next_time = get_running_time (&sq->src_segment, object, TRUE);
+
GST_LOG_OBJECT (mq, "SingleQueue %d : newid:%d , oldid:%d",
sq->id, newid, sq->last_oldid);
* or it's the first loop, or we just passed the previous highid,
* we might need to wake some sleeping pad up, so there's extra work
* there too */
- if (sq->srcresult == GST_FLOW_NOT_LINKED ||
- (sq->last_oldid == G_MAXUINT32) || (newid != (sq->last_oldid + 1)) ||
- sq->last_oldid > mq->highid) {
+ if (sq->srcresult == GST_FLOW_NOT_LINKED
+ || (sq->last_oldid == G_MAXUINT32) || (newid != (sq->last_oldid + 1))
+ || sq->last_oldid > mq->highid) {
GST_LOG_OBJECT (mq, "CHECKING sq->srcresult: %s",
gst_flow_get_name (sq->srcresult));
/* Update the nextid so other threads know when to wake us up */
sq->nextid = newid;
+ sq->next_time = next_time;
/* Update the oldid (the last ID we output) for highid tracking */
if (sq->last_oldid != G_MAXUINT32)
/* Recompute the highid */
compute_high_id (mq);
- while (newid > mq->highid && sq->srcresult == GST_FLOW_NOT_LINKED) {
- GST_DEBUG_OBJECT (mq, "queue %d sleeping for not-linked wakeup with "
- "newid %u and highid %u", sq->id, newid, mq->highid);
+ /* Recompute the high time */
+ compute_high_time (mq);
+ while (((mq->sync_by_running_time && next_time != GST_CLOCK_TIME_NONE &&
+ (mq->high_time == GST_CLOCK_TIME_NONE
+ || next_time >= mq->high_time))
+ || (!mq->sync_by_running_time && newid > mq->highid))
+ && sq->srcresult == GST_FLOW_NOT_LINKED) {
+
+ GST_DEBUG_OBJECT (mq,
+ "queue %d sleeping for not-linked wakeup with "
+ "newid %u, highid %u, next_time %" GST_TIME_FORMAT
+ ", high_time %" GST_TIME_FORMAT, sq->id, newid, mq->highid,
+ GST_TIME_ARGS (next_time), GST_TIME_ARGS (mq->high_time));
/* Wake up all non-linked pads before we sleep */
wake_up_next_non_linked (mq);
goto out_flushing;
}
+ /* Recompute the high time */
+ compute_high_time (mq);
+
GST_DEBUG_OBJECT (mq, "queue %d woken from sleeping for not-linked "
- "wakeup with newid %u and highid %u", sq->id, newid, mq->highid);
+ "wakeup with newid %u, highid %u, next_time %" GST_TIME_FORMAT
+ ", high_time %" GST_TIME_FORMAT, sq->id, newid, mq->highid,
+ GST_TIME_ARGS (next_time), GST_TIME_ARGS (mq->high_time));
}
/* Re-compute the high_id in case someone else pushed */
/* Wake up all non-linked pads */
wake_up_next_non_linked (mq);
}
- /* We're done waiting, we can clear the nextid */
+ /* We're done waiting, we can clear the nextid and nexttime */
sq->nextid = 0;
+ sq->next_time = GST_CLOCK_TIME_NONE;
GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
}
GST_LOG_OBJECT (mq, "BEFORE PUSHING sq->srcresult: %s",
gst_flow_get_name (sq->srcresult));
+ /* Update time stats */
+ next_time = get_running_time (&sq->src_segment, object, FALSE);
+ if (next_time != GST_CLOCK_TIME_NONE) {
+ if (sq->last_time == GST_CLOCK_TIME_NONE || sq->last_time < next_time)
+ sq->last_time = next_time;
+ if (mq->high_time == GST_CLOCK_TIME_NONE || mq->high_time <= next_time) {
+ /* Wake up all non-linked pads now that we advanceed the high time */
+ mq->high_time = next_time;
+ wake_up_next_non_linked (mq);
+ }
+ }
+
/* Try to push out the new object */
result = gst_single_queue_push_one (mq, sq, object);
sq->srcresult = result;
gst_flow_get_name (sq->srcresult));
sq->last_oldid = newid;
+
return;
out_flushing:
GstSingleQueue *sq = (GstSingleQueue *) tmp->data;
if (sq->srcresult == GST_FLOW_NOT_LINKED) {
- if (sq->nextid != 0 && sq->nextid <= mq->highid) {
+ if ((mq->sync_by_running_time && mq->high_time != GST_CLOCK_TIME_NONE
+ && sq->next_time != GST_CLOCK_TIME_NONE
+ && sq->next_time >= mq->high_time)
+ || (sq->nextid != 0 && sq->nextid <= mq->highid)) {
GST_LOG_OBJECT (mq, "Waking up singlequeue %d", sq->id);
g_cond_signal (sq->turn);
}
lowest);
}
+/* WITH LOCK TAKEN */
+static void
+compute_high_time (GstMultiQueue * mq)
+{
+ /* The high-id is either the highest id among the linked pads, or if all
+ * pads are not-linked, it's the lowest not-linked pad */
+ GList *tmp;
+ GstClockTime highest = GST_CLOCK_TIME_NONE;
+ GstClockTime lowest = GST_CLOCK_TIME_NONE;
+
+ for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) {
+ GstSingleQueue *sq = (GstSingleQueue *) tmp->data;
+
+ GST_LOG_OBJECT (mq,
+ "inspecting sq:%d , next_time:%" GST_TIME_FORMAT ", last_time:%"
+ GST_TIME_FORMAT ", srcresult:%s", sq->id, GST_TIME_ARGS (sq->next_time),
+ GST_TIME_ARGS (sq->last_time), gst_flow_get_name (sq->srcresult));
+
+ if (sq->srcresult == GST_FLOW_NOT_LINKED) {
+ /* No need to consider queues which are not waiting */
+ if (sq->next_time == GST_CLOCK_TIME_NONE) {
+ GST_LOG_OBJECT (mq, "sq:%d is not waiting - ignoring", sq->id);
+ continue;
+ }
+
+ if (lowest == GST_CLOCK_TIME_NONE || sq->next_time < lowest)
+ lowest = sq->next_time;
+ } else if (sq->srcresult != GST_FLOW_UNEXPECTED) {
+ /* If we don't have a global highid, or the global highid is lower than
+ * this single queue's last outputted id, store the queue's one,
+ * unless the singlequeue is at EOS (srcresult = UNEXPECTED) */
+ if (highest == GST_CLOCK_TIME_NONE || sq->last_time > highest)
+ highest = sq->last_time;
+ }
+ }
+
+ mq->high_time = highest;
+
+ GST_LOG_OBJECT (mq,
+ "High time is now : %" GST_TIME_FORMAT ", lowest non-linked %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (mq->high_time), GST_TIME_ARGS (lowest));
+}
+
#define IS_FILLED(q, format, value) (((q)->max_size.format) != 0 && \
((q)->max_size.format) <= (value))
sq->nextid = 0;
sq->oldid = 0;
+ sq->next_time = GST_CLOCK_TIME_NONE;
+ sq->last_time = GST_CLOCK_TIME_NONE;
sq->turn = g_cond_new ();
sq->sinktime = GST_CLOCK_TIME_NONE;
index b9c28cd442c597f59d0cd5d5da9e3849184c2e55..bb3d840420be816614490049d465c0d0db8596cf 100644 (file)
struct _GstMultiQueue {
GstElement element;
+ gboolean sync_by_running_time;
+
/* number of queues */
guint nbqueues;
guint32 counter; /* incoming object counter, use atomic accesses */
guint32 highid; /* contains highest id of last outputted object */
+ GstClockTime high_time; /* highest start running time */
GMutex * qlock; /* Global queue lock (vs object lock or individual */
/* queues lock). Protects nbqueues, queues, global */
index f3ce6e295d7f283c2eae3cc272beb1a2d897c451..30072198367205986c22cb2dbfa7f87c0b123f7b 100644 (file)
sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad));
if (G_UNLIKELY (sel == NULL))
return GST_FLOW_WRONG_STATE;
- res = GST_FLOW_NOT_LINKED;
GST_OBJECT_LOCK (sel);
allocpad = sel->pending_srcpad ? sel->pending_srcpad : sel->active_srcpad;
index 436323c0b03aa5c43c3fd85baebfa0dd889c4ad2..f1dce4b0c7394bb0fe88a4e5afdf54d4f1311350 100644 (file)
queue->bytes_in = 0;
queue->bytes_out = 0;
queue->byte_in_rate = 0.0;
+ queue->byte_in_period = 0;
queue->byte_out_rate = 0.0;
queue->last_in_elapsed = 0.0;
queue->last_out_elapsed = 0.0;
/* Tuning for rate estimation. We use a large window for the input rate because
* it should be stable when connected to a network. The output rate is less
* stable (the elements preroll, queues behind a demuxer fill, ...) and should
- * therefore adapt more quickly. */
-#define AVG_IN(avg,val) ((avg) * 15.0 + (val)) / 16.0
+ * therefore adapt more quickly.
+ * However, initial input rate may be subject to a burst, and should therefore
+ * initially also adapt more quickly to changes, and only later on give higher
+ * weight to previous values. */
+#define AVG_IN(avg,val,w1,w2) ((avg) * (w1) + (val) * (w2)) / ((w1) + (w2))
#define AVG_OUT(avg,val) ((avg) * 3.0 + (val)) / 4.0
static void
period = elapsed - queue->last_in_elapsed;
GST_DEBUG_OBJECT (queue,
- "rates: period %f, in %" G_GUINT64_FORMAT, period, queue->bytes_in);
+ "rates: period %f, in %" G_GUINT64_FORMAT ", global period %f",
+ period, queue->bytes_in, queue->byte_in_period);
byte_in_rate = queue->bytes_in / period;
if (queue->byte_in_rate == 0.0)
queue->byte_in_rate = byte_in_rate;
else
- queue->byte_in_rate = AVG_IN (queue->byte_in_rate, byte_in_rate);
+ queue->byte_in_rate = AVG_IN (queue->byte_in_rate, byte_in_rate,
+ (double) queue->byte_in_period, period);
+
+ /* another data point, cap at 16 for long time running average */
+ if (queue->byte_in_period < 16 * RATE_INTERVAL)
+ queue->byte_in_period += period;
/* reset the values to calculate rate over the next interval */
queue->last_in_elapsed = elapsed;
index 358b43a47a9ffaba8220f4b9e971e148832f20c9..ccbead6a17a1d28fa1c0655b0e7d09f143e42ebf 100644 (file)
gdouble last_in_elapsed;
guint64 bytes_in;
gdouble byte_in_rate;
+ gdouble byte_in_period;
GTimer *out_timer;
gboolean out_timer_started;
diff --git a/po/af.po b/po/af.po
index a181e82b61858c4970ad67c7c9411d4225bd3cc8..dfd93b85b37a9678d702aa9ef0eeed606932313b 100644 (file)
--- a/po/af.po
+++ b/po/af.po
msgstr ""
"Project-Id-Version: gstreamer 0.9.7\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2005-12-05 11:45+0200\n"
"Last-Translator: Petri Jooste <rkwjpj@puk.ac.za>\n"
"Language-Team: Afrikaans <i18n@af.org.za>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Pyplyn word gestel na NULL ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "geen element \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Wys etikette (ook bekend as metadata)"
diff --git a/po/az.po b/po/az.po
index 4ce2582aa7149e5134bda470a7972e27a2829a37..c022a6be8c8559ec40639ae87d858e3b20745e07 100644 (file)
--- a/po/az.po
+++ b/po/az.po
msgstr ""
"Project-Id-Version: gstreamer-0.8.0\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2004-03-19 18:40+0200\n"
"Last-Translator: Metin Amiroff <metin@karegen.com>\n"
"Language-Team: Azerbaijani <translation-team-az@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, c-format
+msgid "Missing element: %s\n"
+msgstr ""
+
msgid "Output tags (also known as metadata)"
msgstr ""
diff --git a/po/be.po b/po/be.po
index dbd76abf8b015b97b6075f75de766ab53cecf409..6da856d2bb67f222e03a9614c571dadace700d33 100644 (file)
--- a/po/be.po
+++ b/po/be.po
msgstr ""
"Project-Id-Version: gstreamer 0.9.7\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2006-01-18 22:26+0200\n"
"Last-Translator: Ales Nyakhaychyk <nab@mail.by>\n"
"Language-Team: Belarusian <i18n@mova.org>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, c-format
+msgid "Missing element: %s\n"
+msgstr ""
+
msgid "Output tags (also known as metadata)"
msgstr ""
diff --git a/po/bg.po b/po/bg.po
index 4c9489d0687f4c94f8a83c0846102af9c3d27f43..29d96ef67bbca8875e1d8f7ad24d09ba058f5c95 100644 (file)
--- a/po/bg.po
+++ b/po/bg.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.32.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-04-26 22:40+0300\n"
"Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
"Language-Team: Bulgarian <dict@fsa-bg.org>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Прекъсване: Конвейерът се спира…\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "елементът „%s“ липсва"
+
msgid "Output tags (also known as metadata)"
msgstr "Изходни съобщения за етикетите (метаданните)"
diff --git a/po/ca.po b/po/ca.po
index 0edb1bfb95381f12244198e35d9dbce38e49bdc1..bebce39be1ed3847c9a96fa67864b971d95dd9a1 100644 (file)
--- a/po/ca.po
+++ b/po/ca.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-11-04 19:41+0100\n"
"Last-Translator: Jordi Mallach <jordi@sindominio.net>\n"
"Language-Team: Catalan <ca@dodds.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interrupció: S'està aturant el conducte…\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "no hi ha cap element «%s»"
+
msgid "Output tags (also known as metadata)"
msgstr "Mostra els marcadors (també coneguts com metadades)"
diff --git a/po/cs.po b/po/cs.po
index 4e42da628eceea19628bfe9626e5587682f0c8ca..19176b4555019eab742f140217988b414222217a 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.20.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2008-10-12 12:12+0200\n"
"Last-Translator: Miloslav Trmac <mitr@volny.cz>\n"
"Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Přerušení: Zastavuji rouru ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "element \"%s\" neexistuje"
+
msgid "Output tags (also known as metadata)"
msgstr "Vypsat tagy (také známé jako metadata)"
diff --git a/po/da.po b/po/da.po
index 813661a6d9f203d7ab1df2b70c762d1d406eae6b..f9bdaf843446d19e2f99787f4f220b3fedc57f95 100644 (file)
--- a/po/da.po
+++ b/po/da.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-11-06 22:52+0100\n"
"Last-Translator: Mogens Jaeger <mogensjaeger@gmail.com>\n"
"Language-Team: Danish <dansk@dansk-gruppen.dk>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Afbrydelse: Stopper rørledning...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "intet element \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Uddatamærkater (også kendt som metadata)"
diff --git a/po/de.po b/po/de.po
index cc8741a0c4086ef334984ad2f36d47109b5035fa..36f8ae4138881620bfdf1a36f44d59b36341b6e3 100644 (file)
--- a/po/de.po
+++ b/po/de.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.32.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-04-27 23:44+0200\n"
"Last-Translator: Christian Kirbach <christian.kirbach@googlemail.com>\n"
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interrupt: Leitung wird gestoppt ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "Kein Element »%s«"
+
msgid "Output tags (also known as metadata)"
msgstr "Kennzeichen (auch bekannt als Metadaten) ausgeben"
diff --git a/po/el.po b/po/el.po
index c4409ca7bf7d08cc252c69816663b8959be30462..f2585be49a4b9f083c4da582f16befdd3b04419e 100644 (file)
--- a/po/el.po
+++ b/po/el.po
msgstr ""
"Project-Id-Version: gstreamer-0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-11-29 11:14+0200\n"
"Last-Translator: Michael Kotsarinis <mk73628@gmail.com>\n"
"Language-Team: Greek <team@lists.gnome.gr>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Διακοπή: Τερματισμός διασωλήνωσης…\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "δεν υπάρχει στοιχείο «%s»"
+
msgid "Output tags (also known as metadata)"
msgstr "Ετικέτες εξόδου (επίσης γνωστές ως μεταδεδομένα)"
diff --git a/po/en_GB.po b/po/en_GB.po
index f77ab29856bb1d23eccf63cf972af6f655f03712..fd70295d38435b660c31b0d6e9c95120cb6a1ffa 100644 (file)
--- a/po/en_GB.po
+++ b/po/en_GB.po
msgstr ""
"Project-Id-Version: gstreamer 0.8.1\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2004-04-26 10:36-0400\n"
"Last-Translator: Gareth Owen <gowen72@yahoo.com>\n"
"Language-Team: English (British) <en_gb@li.org>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "no element \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Output tags (also known as metadata)"
diff --git a/po/es.po b/po/es.po
index c579819a8848cf42b2f354e9fddfe9d4ffa5a4a7..84e17719b5115d9c697232b11b3e513efbb4aec9 100644 (file)
--- a/po/es.po
+++ b/po/es.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-11-01 18:11+0100\n"
"Last-Translator: Jorge González González <aloriel@gmail.com>\n"
"Language-Team: Spanish <es@li.org>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interrumpir: parando el conducto …\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "no hay un elemento «%s»"
+
msgid "Output tags (also known as metadata)"
msgstr "Etiquetas de salida (también conocidos como metadatos)"
diff --git a/po/eu.po b/po/eu.po
index 529077fb5dc0f5c1372a150c27f16ddfb7a21b1a..ddd431a7b514e66cf24ad35011a3d129d93d9c89 100644 (file)
--- a/po/eu.po
+++ b/po/eu.po
msgstr ""
"Project-Id-Version: gstreamer-0.10.26.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-03-25 13:10+0100\n"
"Last-Translator: Mikel Olasagasti Uranga <hey_neken@mundurat.net>\n"
"Language-Team: Basque <translation-team-eu@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Eten: Kanalizazioa gelditzen... \n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "ez dago \"%s\" elementua"
+
msgid "Output tags (also known as metadata)"
msgstr "Erakutsi etiketak (metadatu gisa ere ezagutzen direnak)"
diff --git a/po/fi.po b/po/fi.po
index 1add3ba935eebdbb821d09ee0016a9d847d8e5dd..0f77f4d01c64c0a55bb74449c15b75c41638de1d 100644 (file)
--- a/po/fi.po
+++ b/po/fi.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-11-17 23:10+0200\n"
"Last-Translator: Tommi Vainikainen <Tommi.Vainikainen@iki.fi>\n"
"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Keskeytys: Pysäytetään liukuhihna ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "ei elementtiä ”%s”"
+
msgid "Output tags (also known as metadata)"
msgstr "Tulostemerkinnät (tunnetaan myös metadatana)"
diff --git a/po/fr.po b/po/fr.po
index 9641e7779ebfca06f4f6f4bab79000ff7db9e721..b4adae0ba6f653474494a9b14b00b1d8ec89a503 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.32.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-04-28 09:34+0200\n"
"Last-Translator: Claude Paroz <claude@2xlibre.net>\n"
"Language-Team: French <traduc@traduc.org>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interruption : arrêt du pipeline...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "pas d'élément « %s »"
+
msgid "Output tags (also known as metadata)"
msgstr "Affiche les balises (aussi connues sous le nom de métadonnées)"
diff --git a/po/gl.po b/po/gl.po
index a58aec8ac23faa4d0cf6a5dd4a02fbb3cb95c736..f456f8f4869a7914f3a4c08791faad3a655ba76d 100644 (file)
--- a/po/gl.po
+++ b/po/gl.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.31.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-04-13 05:19+0000\n"
"Last-Translator: Francisco Diéguez <frandieguez@ubuntu.com>\n"
"Language-Team: Galician <proxecto@trasno.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interromper: parando a canalización …\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "non hai un elemento «%s»"
+
msgid "Output tags (also known as metadata)"
msgstr "Etiquetas de saída (tamén coñecido como metadatos)"
diff --git a/po/hu.po b/po/hu.po
index 74b2fd76f13a97b6fe5310afa342b2a4c94ce1a0..ebe852157b028806aab0d2a4de021dc51f39ac99 100644 (file)
--- a/po/hu.po
+++ b/po/hu.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-11-01 13:39+0100\n"
"Last-Translator: Gabor Kelemen <kelemeng@gnome.hu>\n"
"Language-Team: Hungarian <translation-team-hu@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Megszakítás: Adatcsatorna leállítása…\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "nincs „%s” elem"
+
msgid "Output tags (also known as metadata)"
msgstr "Kimeneti címkék (metaadatok)"
diff --git a/po/id.po b/po/id.po
index ea40ed1338f22df2521c7b84efba55eb1589faae..9b88775bd57bdea991e10de1d23ecf3e8ca31d9f 100644 (file)
--- a/po/id.po
+++ b/po/id.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.29.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-06-29 21:55+0700\n"
"Last-Translator: Andhika Padmawan <andhika.padmawan@gmail.com>\n"
"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interupsi: Menghentikan baris pipa ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "tak ada elemen \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Tag keluaran (juga dikenal sebagai metadata)"
diff --git a/po/it.po b/po/it.po
index c48f6706f9e6905a5b03d635acf7079584ddcf97..f26d74054cec3ef29c515edf0c10b934c3816322 100644 (file)
--- a/po/it.po
+++ b/po/it.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-10-25 10:03+0200\n"
"Last-Translator: Luca Ferretti <elle.uca@infinito.it>\n"
"Language-Team: Italian <tp@lists.linux.it>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interrotto: arresto della pipeline ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "nessun elemento «%s»"
+
# -t, --tags
msgid "Output tags (also known as metadata)"
msgstr "Stampa i tag (anche noti come metadati)"
diff --git a/po/ja.po b/po/ja.po
index dc0d8c55bd06c6a097abe1c91fb97ee39a0c5692..6cab73a70c80e6cb8183a07dad5d4fb6907e6c76 100644 (file)
--- a/po/ja.po
+++ b/po/ja.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.20.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2008-10-16 19:57+0900\n"
"Last-Translator: Makoto Kato <makoto.kt@gmail.com>\n"
"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "割り込み: パイプラインを停止しています...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "エレメント \"%s\" がありません"
+
msgid "Output tags (also known as metadata)"
msgstr "タグ (メタデータ) を出力する"
diff --git a/po/lt.po b/po/lt.po
index 119cf67ef21f17f8015f82e2eaecca741ef1864b..0ea69f54794bb103ba510f58a7641acf39702404 100644 (file)
--- a/po/lt.po
+++ b/po/lt.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.29.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-07-16 00:50+0300\n"
"Last-Translator: Žygimantas Beručka <uid0@akl.lt>\n"
"Language-Team: Lithuanian <komp_lt@konferencijos.lt>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Pertraukimas: stabdomas konvejeris...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "nėra elemento „%s“"
+
msgid "Output tags (also known as metadata)"
msgstr "Išvesti žymas (dar žinomas kaip metaduomenys)"
diff --git a/po/nb.po b/po/nb.po
index 0fd1f5bb31706d57d9283db881e023f449ee4500..c9d96c98fbbcdf31b4d7517963540da06e2dcf94 100644 (file)
--- a/po/nb.po
+++ b/po/nb.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-10-24 21:36+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian Bokmaal <i18n-nb@lister.ping.uio.no>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "ingen element «%s»"
+
msgid "Output tags (also known as metadata)"
msgstr ""
diff --git a/po/nl.po b/po/nl.po
index 65965491ea3da1c72d4c2fa30417fa6984fea0a1..03852216c8bdfdca8086ca2f10e2a36e015df7f5 100644 (file)
--- a/po/nl.po
+++ b/po/nl.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.32.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-04-26 23:10+0200\n"
"Last-Translator: Freek de Kruijf <f.de.kruijf@gmail.com>\n"
"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interrupt: Pijplijn ingesteld op gestopt ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "geen element \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Tags (ook bekend als metadata) weergeven"
diff --git a/po/pl.po b/po/pl.po
index aa1e2db30f55a7ea61650e218128f174ebfb17dd..f49bb2237297f53b9e33e9267855035d25616dd1 100644 (file)
--- a/po/pl.po
+++ b/po/pl.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.32.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-04-26 17:54+0200\n"
"Last-Translator: Jakub Bogusz <qboosh@pld-linux.org>\n"
"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Przerwanie: Zatrzymywanie potoku...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "brak elementu \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Wypisanie znaczników (znanych także jako metadane)"
diff --git a/po/pt_BR.po b/po/pt_BR.po
index d144759925bf21ab7e88d306986305f911b0348a..4a59558b9b930defbcc98083f8d361eee4d13f2c 100644 (file)
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
msgstr ""
"Project-Id-Version: gstreamer-0.10.31.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-01-08 01:36-0300\n"
"Last-Translator: Fabrício Godoy <skarllot@gmail.com>\n"
"Language-Team: Brazilian Portuguese <ldp-br@bazar.conectiva.com.br>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Interrupção: Parando a fila de processamento...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "nenhum elemento \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Exibir etiquetas (metadados)"
diff --git a/po/ro.po b/po/ro.po
index e7e7e3f966d47dcfc4afcfce12a79ed28939c14f..ab39aac88f0ec5691a912754fd0a28861c084d99 100644 (file)
--- a/po/ro.po
+++ b/po/ro.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.29.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-08-16 01:10+0300\n"
"Last-Translator: Lucian Adrian Grijincu <lucian.grijincu@gmail.com>\n"
"Language-Team: Romanian <translation-team-ro@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Întrerupere: Se oprește linia de asamblare ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "niciun element „%s”"
+
msgid "Output tags (also known as metadata)"
msgstr "Marcaje de ieșire (cunoscute și ca „metadata”)"
diff --git a/po/ru.po b/po/ru.po
index 2300900452d2fd0cdf5354b9e9e2f83d9fcdd2d2..0144f7cbd33f1a030d6e1bfe04251416fb4e8301 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
msgstr ""
"Project-Id-Version: gstreamer-0.10.32.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-04-26 20:25+0400\n"
"Last-Translator: Yuri Kozlov <yuray@komyakino.ru>\n"
"Language-Team: Russian <gnu@mx.ru>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Прерывание: Остановка конвейера...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "элемент «%s» не найден"
+
msgid "Output tags (also known as metadata)"
msgstr "Выводить теги (метаданные)"
diff --git a/po/rw.po b/po/rw.po
index 6200b2fcf573b4c4a817b7977609e7f19efeee69..7178bad144e5c494ace64f0c14700a921cd3b9b0 100644 (file)
--- a/po/rw.po
+++ b/po/rw.po
msgstr ""
"Project-Id-Version: gstreamer 0.8.8\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2005-04-04 10:55-0700\n"
"Last-Translator: Steven Michael Murphy <murf@e-tools.com>\n"
"Language-Team: Kinyarwanda <translation-team-rw@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "Oya Ikigize:"
+
#, fuzzy
msgid "Output tags (also known as metadata)"
msgstr "Nka"
diff --git a/po/sk.po b/po/sk.po
index 7c266a1fbba9e6cb6564a7c16fb044c8b4af819e..f818a54e51589ac5b47db0d0cbe82eb7c5291a63 100644 (file)
--- a/po/sk.po
+++ b/po/sk.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.30.3\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-11-08 16:13+0100\n"
"Last-Translator: Peter Tuhársky <tuharsky@misbb.sk>\n"
"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Prerušenie: Zastavujem rúru ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "prvok \"%s\" neexistuje"
+
msgid "Output tags (also known as metadata)"
msgstr "Vypísať značky (známe tiež ako metadáta)"
diff --git a/po/sl.po b/po/sl.po
index 20996f530c291197da3466cf5d6a503091817961..7f1fe7f44060b9ecb75d2e6f8521abc97a222e5f 100644 (file)
--- a/po/sl.po
+++ b/po/sl.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.29.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-09-18 20:21+0100\n"
"Last-Translator: Matej Urbančič <matej.urban@gmail.com>\n"
"Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Prekinitev: zaustavljanje predvajanja vsebine cevovoda ... \n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "ni predmeta \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr ""
diff --git a/po/sq.po b/po/sq.po
index 2b35a2341483823a30071a175e3170f722e2697d..dbc2ffa7507f7e63dc7d7b844d9601f7dadb2949 100644 (file)
--- a/po/sq.po
+++ b/po/sq.po
msgstr ""
"Project-Id-Version: gstreamer 0.8.4\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2004-08-07 23:46+0200\n"
"Last-Translator: Laurent Dhima <laurenti@alblinux.net>\n"
"Language-Team: Albanian <begraj@hotmail.com>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "asnjë element \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Tags e output (njohur gjithashtu si metadata)"
diff --git a/po/sr.po b/po/sr.po
index 272ed70beda74449ab44053678f675d1368190f3..82810fb59a84f9a188f5e0504f1d0acaa2cb1a93 100644 (file)
--- a/po/sr.po
+++ b/po/sr.po
msgstr ""
"Project-Id-Version: gstreamer 0.8.8\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2005-01-27 16:58+0100\n"
"Last-Translator: Danilo Segan <dsegan@gmx.net>\n"
"Language-Team: Serbian <gnu@prevod.org>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "нема елемента „%s“"
+
msgid "Output tags (also known as metadata)"
msgstr "Излазне ознаке (такође познато и као метаподаци)"
diff --git a/po/sv.po b/po/sv.po
index adbde5621722a5351fb408b1caa1aac20ec57113..d27e686961a8da4c9c314011b5482fe712177e4e 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.31.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2011-01-09 19:46+0100\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Avbrott: Stoppar rörledningen ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "inget \"%s\"-element"
+
msgid "Output tags (also known as metadata)"
msgstr "Utmatningstaggar (även känt som metadata)"
diff --git a/po/tr.po b/po/tr.po
index a4c2a40c8f4a08b87e3698a9e7b028a5df62e1a2..d973ac9baeaf1e918f6926c454433b0f2f28943e 100644 (file)
--- a/po/tr.po
+++ b/po/tr.po
msgstr ""
"Project-Id-Version: gstreamer 0.8.0\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2004-04-03 03:14+0300\n"
"Last-Translator: Baris Cicek <baris@teamforce.name.tr>\n"
"Language-Team: Turkish <gnu-tr-u12a@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "\"%s\" öğesi yok"
+
msgid "Output tags (also known as metadata)"
msgstr "Çıktı etiketleri (metadata olarak da bilinir)"
diff --git a/po/uk.po b/po/uk.po
index 50b36d9c7d02491a01f5ff603e65dce8bab09e0a..70d9a32b5405827e0a8f084e82fa75981846878d 100644 (file)
--- a/po/uk.po
+++ b/po/uk.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.14\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2007-09-07 11:16+0300\n"
"Last-Translator: Maxim V. Dziumanenko <dziumanenko@gmail.com>\n"
"Language-Team: Ukrainian <translation-team-uk@lists.sourceforge.net>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Переривання: Канал переводиться у стан ПРИЗУПИНЕНО ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "немає елементу \"%s\""
+
msgid "Output tags (also known as metadata)"
msgstr "Вивести теги (також відомі як метадані)"
diff --git a/po/vi.po b/po/vi.po
index d95c7a04cc0c9e6b0449bd88c6767f219c975d25..6dafb70c78af5983a01e82af8791d3f38b6100ba 100644 (file)
--- a/po/vi.po
+++ b/po/vi.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.29.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-10-03 19:09+1030\n"
"Last-Translator: Clytie Siddall <clytie@riverland.net.au>\n"
"Language-Team: Vietnamese <vi-VN@googlegroups.com>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "Ngắt: đang ngừng chạy đường ống ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "không có yếu tố « %s »"
+
msgid "Output tags (also known as metadata)"
msgstr "Thể xuất (cũng được biết là siêu dữ liệu)"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index daaf2027bd2cad09761b81a9c289ff67c40bc814..92a1d9e41e6dc1cadcafda45115b9992dfee7220 100644 (file)
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
msgstr ""
"Project-Id-Version: gstreamer 0.10.25.2\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2010-02-02 18:58+0800\n"
"Last-Translator: Ji ZhengYu <zhengyuji@gmail.com>\n"
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr "中断: 中止管道 ...\n"
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "无组件“%s”"
+
msgid "Output tags (also known as metadata)"
msgstr "输出标识(也可认为是元数据)"
diff --git a/po/zh_TW.po b/po/zh_TW.po
index 4a83e2121446b83b6b47c6c6040d4ec0272d21ba..7bb8fee216f01aa1cf83f5846de921128daceae5 100644 (file)
--- a/po/zh_TW.po
+++ b/po/zh_TW.po
msgstr ""
"Project-Id-Version: gstreamer 0.8.8\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n"
-"POT-Creation-Date: 2011-05-10 08:32+0100\n"
+"POT-Creation-Date: 2011-06-04 13:33+0100\n"
"PO-Revision-Date: 2005-04-27 14:55+0800\n"
"Last-Translator: Abel Cheung <abelcheung@gmail.com>\n"
"Language-Team: Chinese (traditional) <zh-l10n@linux.org.tw>\n"
msgid "Interrupt: Stopping pipeline ...\n"
msgstr ""
+#, fuzzy, c-format
+msgid "Missing element: %s\n"
+msgstr "“%s” 元件不存在"
+
msgid "Output tags (also known as metadata)"
msgstr ""
index fa160d91dd3320d8611fbb0bae7a5d55d466175c..cd8b9d0b3b331f7b6820e4c6c9865df669f5a6b9 100644 (file)
GST_END_TEST;
+GST_START_TEST (test_subset)
+{
+ GstCaps *c1, *c2;
+
+ c1 = gst_caps_from_string ("video/x-raw-yuv; video/x-raw-rgb");
+ c2 = gst_caps_from_string ("video/x-raw-yuv, format=(fourcc)YUY2");
+ fail_unless (gst_caps_is_subset (c2, c1));
+ fail_if (gst_caps_is_subset (c1, c2));
+ gst_caps_unref (c1);
+ gst_caps_unref (c2);
+
+ c1 = gst_caps_from_string
+ ("audio/x-raw-int, channels=(int)[ 1, 2 ], rate=(int)44100");
+ c2 = gst_caps_from_string
+ ("audio/x-raw-int, channels=(int)1, rate=(int)44100");
+ fail_unless (gst_caps_is_subset (c2, c1));
+ fail_if (gst_caps_is_subset (c1, c2));
+ gst_caps_unref (c1);
+ gst_caps_unref (c2);
+
+ c1 = gst_caps_from_string ("audio/x-raw-int, channels=(int) {1}");
+ c2 = gst_caps_from_string ("audio/x-raw-int, channels=(int)1");
+ fail_unless (gst_caps_is_subset (c2, c1));
+ fail_unless (gst_caps_is_subset (c1, c2));
+ fail_unless (gst_caps_is_equal (c1, c2));
+ gst_caps_unref (c1);
+ gst_caps_unref (c2);
+
+ c1 = gst_caps_from_string
+ ("audio/x-raw-int, rate=(int)44100, channels=(int)3, endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)false");
+ c2 = gst_caps_from_string
+ ("audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)16, depth=(int)[ 1, 16 ], signed=(boolean){ true, false }");
+ fail_unless (gst_caps_is_subset (c1, c2));
+ fail_if (gst_caps_is_subset (c2, c1));
+ gst_caps_unref (c1);
+ gst_caps_unref (c2);
+}
+
+GST_END_TEST;
+
GST_START_TEST (test_merge_fundamental)
{
GstCaps *c1, *c2;
fail_unless (gst_caps_is_subset (test, c2));
gst_caps_unref (test);
gst_caps_unref (c2);
+
+ c2 = gst_caps_from_string ("audio/x-raw-int");
+ c1 = gst_caps_from_string ("audio/x-raw-int,channels=1");
+ gst_caps_merge (c2, c1);
+ GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+ fail_unless (gst_caps_get_size (c2) == 1, NULL);
+ test = gst_caps_from_string ("audio/x-raw-int");
+ fail_unless (gst_caps_is_equal (c2, test));
+ gst_caps_unref (c2);
+ gst_caps_unref (test);
+
+ c2 = gst_caps_from_string ("audio/x-raw-int,channels=1");
+ c1 = gst_caps_from_string ("audio/x-raw-int");
+ gst_caps_merge (c2, c1);
+ GST_DEBUG ("merged: (%d) %" GST_PTR_FORMAT, gst_caps_get_size (c2), c2);
+ fail_unless (gst_caps_get_size (c2) == 2, NULL);
+ test = gst_caps_from_string ("audio/x-raw-int,channels=1; audio/x-raw-int");
+ fail_unless (gst_caps_is_equal (c2, test));
+ gst_caps_unref (c2);
+ gst_caps_unref (test);
}
GST_END_TEST;
GST_END_TEST;
+GST_START_TEST (test_intersect_duplication)
+{
+ GstCaps *c1, *c2, *test;
+
+ c1 = gst_caps_from_string
+ ("audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]");
+ c2 = gst_caps_from_string
+ ("audio/x-raw-int, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ], endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }; audio/x-raw-int, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 11 ], endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }; audio/x-raw-int, width=(int)16, depth=(int)[ 1, 16 ], rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 11 ], endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }");
+
+ test = gst_caps_intersect_full (c1, c2, GST_CAPS_INTERSECT_FIRST);
+ fail_unless_equals_int (gst_caps_get_size (test), 1);
+ fail_unless (gst_caps_is_equal (c1, test));
+ gst_caps_unref (c1);
+ gst_caps_unref (c2);
+ gst_caps_unref (test);
+}
+
+GST_END_TEST;
static gboolean
_caps_is_fixed_foreach (GQuark field_id, const GValue * value, gpointer unused)
tcase_add_test (tc_chain, test_static_caps);
tcase_add_test (tc_chain, test_simplify);
tcase_add_test (tc_chain, test_truncate);
+ tcase_add_test (tc_chain, test_subset);
tcase_add_test (tc_chain, test_merge_fundamental);
tcase_add_test (tc_chain, test_merge_same);
tcase_add_test (tc_chain, test_merge_subset);
tcase_add_test (tc_chain, test_intersect_zigzag);
tcase_add_test (tc_chain, test_intersect_first);
tcase_add_test (tc_chain, test_intersect_first2);
+ tcase_add_test (tc_chain, test_intersect_duplication);
tcase_add_test (tc_chain, test_normalize);
tcase_add_test (tc_chain, test_broken);
index b78538aaa4a01fbcdb4289d4d3f921c19a6334c9..332f6540a1b3684eb22a0c1250e0d4574d7e8997 100644 (file)
GST_START_TEST (test_link)
{
GstElement *b1, *b2, *src, *sink;
- GstPad *srcpad, *sinkpad, *gpad;
+ GstPad *srcpad, *sinkpad, *gpad, *ppad, *tmp;
GstPadLinkReturn ret;
b1 = gst_element_factory_make ("pipeline", NULL);
/* now setup a ghostpad */
gpad = gst_ghost_pad_new ("sink", sinkpad);
+
+ /* Check if the internal pads are set correctly */
+ ppad = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (gpad)));
+ fail_unless (ppad == GST_PAD_PEER (sinkpad));
+ tmp = GST_PAD (gst_proxy_pad_get_internal (GST_PROXY_PAD (ppad)));
+ fail_unless (tmp == gpad);
+ gst_object_unref (tmp);
+ gst_object_unref (ppad);
gst_object_unref (sinkpad);
/* need to ref as _add_pad takes ownership */
gst_object_ref (gpad);
index 9b9c1cde9cda1ebcadd4bcb4313c4ba240a66882..0a7a7313b22a9c9524a1e93e92d66bda7e44ca90 100644 (file)
GST_END_TEST;
+/* ======== weak ref test ======== */
+
+static gboolean weak_ref_notify_succeeded = FALSE;
+
+static void
+on_weak_ref_notify (gpointer data, GstMiniObject * where_object_was)
+{
+ weak_ref_notify_succeeded = TRUE;
+}
+
+GST_START_TEST (test_weak_ref)
+{
+ GstBuffer *buffer;
+
+ buffer = gst_buffer_new_and_alloc (4);
+
+ gst_mini_object_weak_ref (GST_MINI_OBJECT (buffer), on_weak_ref_notify,
+ &buffer);
+
+ gst_buffer_unref (buffer);
+
+ fail_unless (weak_ref_notify_succeeded,
+ "No weak reference notification took place.");
+}
+
+GST_END_TEST;
+
/* ======== recycle test ======== */
static gint recycle_buffer_count = 10;
tcase_add_test (tc_chain, test_make_writable);
tcase_add_test (tc_chain, test_ref_threaded);
tcase_add_test (tc_chain, test_unref_threaded);
+ tcase_add_test (tc_chain, test_weak_ref);
tcase_add_test (tc_chain, test_recycle_threaded);
tcase_add_test (tc_chain, test_value_collection);
tcase_add_test (tc_chain, test_dup_null_mini_object);
index 533674f3947b20b1ced2e3feece67397c9268777..23ac70ed86a2b5618951a2ae903293116bccb1f1 100644 (file)
{"GstTypeFindFactoryClass", sizeof (GstTypeFindFactoryClass), 152},
{"GstURIHandlerInterface", sizeof (GstURIHandlerInterface), 44},
{"GstValueTable", sizeof (GstValueTable), 32},
+#if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_DISABLE_DEPRECATED) && !defined(GST_REMOVE_DEPRECATED)
{"GstXML", sizeof (GstXML), 64},
{"GstXMLClass", sizeof (GstXMLClass), 144},
+#endif
{NULL, 0, 0}
};
index 3c7fdf9f6588ab64c0f28e266b0f5efc46f2b247..072ef74952ef746c51be77e14a3b875503d6c4ad 100644 (file)
#define PIPELINE11 "fakesink silent=true name = sink identity silent=true name=id ( fakesrc num-buffers=\"4\" ! id. ) id. ! sink."
#define PIPELINE12 "file:///tmp/test.file ! fakesink silent=true"
#define PIPELINE13 "fakesrc ! file:///tmp/test.file"
+#define PIPELINE14 "capsfilter caps=application/x-rtp,sprop-parameter-sets=(string)\"x\\,x\""
+#define PIPELINE15 "capsfilter caps=application/x-rtp,sprop-parameter-sets=(string)\"x\\\"x\\,x\""
GST_START_TEST (test_launch_lines2)
{
* This should warn, but ignore the error and carry on */
cur = setup_pipeline ("( filesrc blocksize=4 location=/dev/null @ )");
gst_object_unref (cur);
+
+ /**
+ * Checks if characters inside quotes are not escaped.
+ */
+ cur = setup_pipeline (PIPELINE14);
+ gst_object_unref (cur);
+
+ /**
+ * Checks if escaped quotes inside quotes are not treated as end string quotes.
+ * This would make the rest of characters to be escaped incorrectly.
+ */
+ cur = setup_pipeline (PIPELINE15);
+ gst_object_unref (cur);
}
GST_END_TEST;
index 8d52ba6d429d493c361d95c7a9c4e94fe1d8975a..d06e0d6a697e6558dd07816ae68f6a8736c3509c 100644 (file)
GST_PLUGIN_SYSTEM_PATH= \
GST_PLUGIN_PATH=$(top_builddir)/plugins
-CLEANFILES = core core.* test-registry.* *.gcno *.gcda
-
EXTRA_DIST = extract.pl
EXAMPLES = \
decodebin \
$(GST_LOADSAVE_SRC)
+BUILT_SOURCES = \
+ elementmake.c elementcreate.c elementget.c elementlink.c elementfactory.c \
+ bin.c \
+ pad.c ghostpad.c \
+ gnome.c \
+ helloworld.c \
+ init.c \
+ query.c \
+ typefind.c dynamic.c \
+ fakesrc.c \
+ playbin.c decodebin.c
+
+CLEANFILES = core core.* test-registry.* *.gcno *.gcda $(BUILT_SOURCES)
+
AM_CFLAGS = $(GST_OBJ_CFLAGS)
LDADD = $(top_builddir)/libs/gst/base/libgstbase-@GST_MAJORMINOR@.la \
$(GST_OBJ_LIBS)
elementmake.c elementcreate.c elementget.c elementlink.c elementfactory.c: $(top_srcdir)/docs/manual/basics-elements.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/basics-elements.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
bin.c : $(top_srcdir)/docs/manual/basics-bins.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/basics-bins.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
pad.c ghostpad.c: $(top_srcdir)/docs/manual/basics-pads.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/basics-pads.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
gnome.c: $(top_srcdir)/docs/manual/appendix-integration.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/appendix-integration.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
helloworld.c: $(top_srcdir)/docs/manual/basics-helloworld.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/basics-helloworld.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
init.c: $(top_srcdir)/docs/manual/basics-init.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/basics-init.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
query.c: $(top_srcdir)/docs/manual/advanced-position.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/advanced-position.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
typefind.c dynamic.c: $(top_srcdir)/docs/manual/advanced-autoplugging.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/advanced-autoplugging.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
fakesrc.c: $(top_srcdir)/docs/manual/advanced-dataaccess.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/advanced-dataaccess.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
playbin.c decodebin.c: $(top_srcdir)/docs/manual/highlevel-components.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/highlevel-components.xml
-
-xml-mp3.c: $(top_srcdir)/docs/manual/highlevel-xml.xml
- $(PERL_PATH) $(srcdir)/extract.pl $@ \
- $(top_srcdir)/docs/manual/highlevel-xml.xml
+ $(PERL_PATH) $(srcdir)/extract.pl $@ $<
TESTS = bin \
elementcreate elementfactory elementget elementlink elementmake \
diff --git a/tools/gst-inspect.c b/tools/gst-inspect.c
index c86285e68af594c0c30e3c3ed87228cab94f70bf..c8f51e5dd4009c8d47104a04fb2caa0c5bba5dd8 100644 (file)
--- a/tools/gst-inspect.c
+++ b/tools/gst-inspect.c
--i;
if (vals[i].value != 0 && (flags_left & vals[i].value) == vals[i].value) {
if (s->len > 0)
- g_string_append (s, " | ");
+ g_string_append_c (s, '+');
g_string_append (s, vals[i].value_nick);
flags_left -= vals[i].value;
if (flags_left == 0)
diff --git a/tools/gst-launch.c b/tools/gst-launch.c
index 2b0d86245e6240d02a33340ed1642aaecd7b98dc..ea99b8f6dda038e61d33b7d8987041dcf1e824d5 100644 (file)
--- a/tools/gst-launch.c
+++ b/tools/gst-launch.c
}
}
+/* Kids, use the functions from libgstpbutils in gst-plugins-base in your
+ * own code (we can't do that here because it would introduce a circular
+ * dependency) */
+static gboolean
+gst_is_missing_plugin_message (GstMessage * msg)
+{
+ if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT || msg->structure == NULL)
+ return FALSE;
+
+ return gst_structure_has_name (msg->structure, "missing-plugin");
+}
+
+static const gchar *
+gst_missing_plugin_message_get_description (GstMessage * msg)
+{
+ return gst_structure_get_string (msg->structure, "name");
+}
+
static void
print_error_message (GstMessage * msg)
{
res = ELR_INTERRUPT;
goto exit;
}
+ break;
+ }
+ case GST_MESSAGE_ELEMENT:{
+ if (gst_is_missing_plugin_message (message)) {
+ const gchar *desc;
+
+ desc = gst_missing_plugin_message_get_description (message);
+ PRINT (_("Missing element: %s\n"), desc ? desc : "(no description)");
+ }
+ break;
}
default:
/* just be quiet by default */
diff --git a/win32/common/config.h b/win32/common/config.h
index 28185bbcfd855783deabb90d5fd0390170207d2c..af2c8e5d1423ab953a0d2427914f3018390b1043 100644 (file)
--- a/win32/common/config.h
+++ b/win32/common/config.h
#define GST_MAJORMINOR "0.10"
/* package name in plugins */
-#define GST_PACKAGE_NAME "GStreamer source release"
+#define GST_PACKAGE_NAME "GStreamer git"
/* package origin */
#define GST_PACKAGE_ORIGIN "Unknown package origin"
/* GStreamer package release date/time for plugins as YYYY-MM-DD */
-#define GST_PACKAGE_RELEASE_DATETIME "2011-06-15"
+#define GST_PACKAGE_RELEASE_DATETIME "2011-06-18T12:45Z"
/* location of the installed gst-plugin-scanner */
#define GST_PLUGIN_SCANNER_INSTALLED LIBDIR "\\gst-plugin-scanner"
#define PACKAGE_NAME "GStreamer"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "GStreamer 0.10.35"
+#define PACKAGE_STRING "GStreamer 0.10.35.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "gstreamer"
#undef PACKAGE_URL
/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.10.35"
+#define PACKAGE_VERSION "0.10.35.1"
/* directory where plugins are located */
#ifdef _DEBUG
#undef USE_POISONING
/* Version number of package */
-#define VERSION "0.10.35"
+#define VERSION "0.10.35.1"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
index 53d56ec772cef521ac03bf7a92258a87fe80e56c..044b1815e73eff3f25a66559e4727f51c12212ae 100644 (file)
* The nano version of GStreamer at compile time:
* Actual releases have 0, GIT versions have 1, prerelease versions have 2-...
*/
-#define GST_VERSION_NANO (0)
+#define GST_VERSION_NANO (1)
/**
* GST_CHECK_VERSION:
index ac43d8b5dceddb62ffcbf7d8b31871eed956075f..b2e831d08617cda6b2093e48126ebe73e556a1be 100644 (file)
gst_base_parse_set_duration
gst_base_parse_set_frame_rate
gst_base_parse_set_has_timing_info
+ gst_base_parse_set_latency
gst_base_parse_set_min_frame_size
gst_base_parse_set_passthrough
gst_base_parse_set_syncable
gst_base_src_query_latency
gst_base_src_set_blocksize
gst_base_src_set_do_timestamp
+ gst_base_src_set_dynamic_size
gst_base_src_set_format
gst_base_src_set_live
gst_base_src_wait_playing
index ca4154d989e759a0f128b26ecb9432a1bf1724e5..a15e0e9ceea8a616a893905a9e0c1fe9640fcc56 100644 (file)
gst_caps_is_equal_fixed
gst_caps_is_fixed
gst_caps_is_subset
+ gst_caps_is_subset_structure
gst_caps_load_thyself
gst_caps_make_writable
gst_caps_merge
gst_fraction_get_type
gst_fraction_range_get_type
gst_g_error_get_type
+ gst_ghost_pad_activate_pull_default
+ gst_ghost_pad_activate_push_default
gst_ghost_pad_construct
gst_ghost_pad_get_target
gst_ghost_pad_get_type
+ gst_ghost_pad_internal_activate_pull_default
+ gst_ghost_pad_internal_activate_push_default
+ gst_ghost_pad_link_default
gst_ghost_pad_new
gst_ghost_pad_new_from_template
gst_ghost_pad_new_no_target
gst_ghost_pad_new_no_target_from_template
gst_ghost_pad_set_target
+ gst_ghost_pad_setcaps_default
+ gst_ghost_pad_unlink_default
gst_implements_interface_cast
gst_implements_interface_check
gst_implements_interface_get_type
gst_mini_object_ref
gst_mini_object_replace
gst_mini_object_unref
+ gst_mini_object_weak_ref
+ gst_mini_object_weak_unref
gst_object_check_uniqueness
gst_object_default_deep_notify
gst_object_default_error
gst_print_element_args
gst_print_pad_caps
gst_progress_type_get_type
+ gst_proxy_pad_acceptcaps_default
+ gst_proxy_pad_bufferalloc_default
+ gst_proxy_pad_chain_default
+ gst_proxy_pad_chain_list_default
+ gst_proxy_pad_checkgetrange_default
+ gst_proxy_pad_event_default
+ gst_proxy_pad_fixatecaps_default
+ gst_proxy_pad_get_internal
gst_proxy_pad_get_type
+ gst_proxy_pad_getcaps_default
+ gst_proxy_pad_getrange_default
+ gst_proxy_pad_iterate_internal_links_default
+ gst_proxy_pad_query_default
+ gst_proxy_pad_query_type_default
+ gst_proxy_pad_setcaps_default
+ gst_proxy_pad_unlink_default
gst_qos_type_get_type
gst_query_add_buffering_range
gst_query_get_n_buffering_ranges
gst_stream_error_get_type
gst_stream_error_quark
gst_stream_status_type_get_type
+ gst_structure_can_intersect
gst_structure_change_type_get_type
gst_structure_copy
gst_structure_empty_new
gst_structure_id_set_valist
gst_structure_id_set_value
gst_structure_id_take_value
+ gst_structure_intersect
+ gst_structure_is_equal
+ gst_structure_is_subset
gst_structure_map_in_place
gst_structure_n_fields
gst_structure_new