]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gstreamer0-10.git/commitdiff
Bump git version after unplanned 0.10.35 release
authorTim-Philipp Müller <tim.muller@collabora.co.uk>
Thu, 16 Jun 2011 16:27:21 +0000 (17:27 +0100)
committerTim-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:
common
configure.ac
docs/faq/general.xml
docs/gst/gstreamer-sections.txt
docs/libs/gstreamer-libs-sections.txt
docs/plugins/gstreamer-plugins.args
docs/plugins/gstreamer-plugins.hierarchy
docs/plugins/gstreamer-plugins.interfaces
docs/plugins/inspect/plugin-coreelements.xml
docs/plugins/inspect/plugin-coreindexers.xml
docs/random/release
gst/gst_private.h
gst/gstbin.c
gst/gstcaps.c
gst/gstcaps.h
gst/gstchildproxy.c
gst/gstclock.h
gst/gstelement.c
gst/gstelement.h
gst/gstghostpad.c
gst/gstghostpad.h
gst/gstmessage.h
gst/gstminiobject.c
gst/gstminiobject.h
gst/gstpad.c
gst/gstpad.h
gst/gstpluginfeature.c
gst/gstpluginfeature.h
gst/gstpreset.c
gst/gstpreset.h
gst/gstregistry.c
gst/gstregistrybinary.h
gst/gstregistrychunks.c
gst/gststructure.c
gst/gststructure.h
gst/gstsystemclock.c
gst/gsttaglist.c
gst/gstvalue.c
gst/parse/Makefile.am
gst/parse/types.h
libs/gst/base/gstbaseparse.c
libs/gst/base/gstbaseparse.h
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasesrc.h
libs/gst/base/gstbasetransform.c
libs/gst/check/gstcheck.h
plugins/elements/gstfdsrc.c
plugins/elements/gstfilesrc.c
plugins/elements/gstinputselector.c
plugins/elements/gstinputselector.h
plugins/elements/gstmultiqueue.c
plugins/elements/gstmultiqueue.h
plugins/elements/gstoutputselector.c
plugins/elements/gstqueue2.c
plugins/elements/gstqueue2.h
po/af.po
po/az.po
po/be.po
po/bg.po
po/ca.po
po/cs.po
po/da.po
po/de.po
po/el.po
po/en_GB.po
po/es.po
po/eu.po
po/fi.po
po/fr.po
po/gl.po
po/hu.po
po/id.po
po/it.po
po/ja.po
po/lt.po
po/nb.po
po/nl.po
po/pl.po
po/pt_BR.po
po/ro.po
po/ru.po
po/rw.po
po/sk.po
po/sl.po
po/sq.po
po/sr.po
po/sv.po
po/tr.po
po/uk.po
po/vi.po
po/zh_CN.po
po/zh_TW.po
tests/check/gst/gstcaps.c
tests/check/gst/gstghostpad.c
tests/check/gst/gstminiobject.c
tests/check/gst/struct_arm.h
tests/check/pipelines/parse-launch.c
tests/examples/manual/Makefile.am
tools/gst-inspect.c
tools/gst-launch.c
win32/common/config.h
win32/common/gstversion.h
win32/common/libgstbase.def
win32/common/libgstreamer.def

diff --git a/common b/common
index 46dfcea233cf6df83e3771d8a8066e87d614f893..69b981f10caa234ad0ff639179d0fda8505bd94b 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 46dfcea233cf6df83e3771d8a8066e87d614f893
+Subproject commit 69b981f10caa234ad0ff639179d0fda8505bd94b
index f625f86a626d3cfd54bc650bacac811865b755ff..0a03ccdd9dd7cd2dbe2a98d702fca61e82c73df8 100644 (file)
@@ -3,7 +3,7 @@ AC_PREREQ(2.60)
 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
@@ -535,7 +535,7 @@ LIBS="$save_libs"
 dnl *** checks for dependency libraries ***
 
 dnl GLib
-GLIB_REQ=2.22
+GLIB_REQ=2.24
 
 AG_GST_GLIB_CHECK([$GLIB_REQ])
 
index 1e6641cf3030ac39f3f2b7264b6e01fae6943ced..60e9b7ddcc9affb5963be0e8e7f86e2520aa9199 100644 (file)
@@ -77,7 +77,7 @@ on the GStreamer project website.
 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)
@@ -323,6 +323,7 @@ gst_caps_is_equal
 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
@@ -902,14 +903,44 @@ gst_format_get_type
 <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
@@ -925,7 +956,6 @@ GST_PROXY_PAD
 GST_PROXY_PAD_CLASS
 GST_TYPE_PROXY_PAD
 GstGhostPadPrivate
-GstProxyPad
 GstProxyPadClass
 GstProxyPadPrivate
 gst_proxy_pad_get_type
@@ -1313,6 +1343,7 @@ GstMiniObject
 GstMiniObjectFlags
 GstMiniObjectCopyFunction
 GstMiniObjectFinalizeFunction
+GstMiniObjectWeakNotify
 
 GST_MINI_OBJECT_FLAGS
 GST_MINI_OBJECT_FLAG_IS_SET
@@ -1330,6 +1361,9 @@ gst_mini_object_ref
 gst_mini_object_unref
 gst_mini_object_replace
 
+gst_mini_object_weak_ref
+gst_mini_object_weak_unref
+
 GstParamSpecMiniObject
 gst_param_spec_mini_object
 
@@ -2175,6 +2209,10 @@ gst_structure_foreach
 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)
@@ -286,6 +286,7 @@ gst_base_src_get_blocksize
 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)
@@ -1,44 +1,43 @@
 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)
@@ -1,6 +1,6 @@
 GstBin GstChildProxy
-GstPipeline GstChildProxy
-GstFdSrc GstURIHandler
-GstFileSrc GstURIHandler
 GstFdSink GstURIHandler
+GstFdSrc GstURIHandler
 GstFileSink GstURIHandler
+GstFileSrc GstURIHandler
+GstPipeline GstChildProxy
index 50ea185af9bc5e0ef8bb937279cf25af9e3f2586..e99c7802aaafe62e25196c916158baa09b34829e 100644 (file)
@@ -3,10 +3,10 @@
   <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>
index b7741d07e5b56da775a1f7191ab3da648ef5ff58..80f072e2a5999959017ef76a61fa0d81c92b943b 100644 (file)
@@ -3,11 +3,11 @@
   <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>
index 6a8a3779e323afe44aaa2f449a7b1c0f1846e2f2..f45bf97c1b17d8405f8d1bacc46bae1256233433 100644 (file)
@@ -129,7 +129,7 @@ RELEASE PROCEDURE:
     + 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
index 2cafbee61102bfd96654f6b0d6bddc44f31375a5..6bd67250fc7051a9bbb933bd22fed65ea560629a 100644 (file)
@@ -51,6 +51,9 @@ extern const char             g_log_domain_gstreamer[];
 /* for the pad cache */
 #include "gstpad.h"
 
+/* for GstElement */
+#include "gstelement.h"
+
 G_BEGIN_DECLS
 
 /* used by gstparse.c and grammar.y */
@@ -113,6 +116,10 @@ gboolean _gst_plugin_loader_client_run (void);
 
 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)
 
@@ -234,5 +241,10 @@ extern GstDebugCategory *_priv_GST_CAT_POLL;
 
 #endif
 
+#ifdef GST_DISABLE_DEPRECATED
+typedef GList*                 (*GstPadIntLinkFunction)        (GstPad *pad);
+#endif
+
+
 G_END_DECLS
 #endif /* __GST_PRIVATE_H__ */
index 73758213e96aecac9d066b709d590e96374d9dd4..89ad34e721855fdc118ab6efb73dc04960520376 100644 (file)
@@ -220,6 +220,8 @@ struct _GstBinPrivate
   GstIndex *index;
   /* forward messages from our children */
   gboolean message_forward;
+
+  gboolean posted_eos;
 };
 
 typedef struct
@@ -238,12 +240,15 @@ static void gst_bin_get_property (GObject * object, guint prop_id,
 
 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);
@@ -502,6 +507,7 @@ gst_bin_class_init (GstBinClass * klass)
 
   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);
@@ -987,10 +993,11 @@ bin_remove_messages (GstBin * bin, GstObject * src, GstMessageType types)
  *
  * 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)) {
@@ -999,8 +1006,11 @@ is_eos (GstBin * bin)
     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));
@@ -1009,7 +1019,13 @@ is_eos (GstBin * bin)
       }
     }
   }
-  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
@@ -2226,24 +2242,23 @@ unneeded:
 }
 
 /* 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)
@@ -2388,6 +2403,19 @@ gst_bin_do_latency_func (GstBin * bin)
   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)
 {
@@ -2428,6 +2456,7 @@ 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)))
@@ -2735,6 +2764,7 @@ gst_bin_continue_func (BinContinueData * data)
 
   GST_STATE_UNLOCK (bin);
   GST_DEBUG_OBJECT (bin, "state continue done");
+
   gst_object_unref (bin);
   g_slice_free (BinContinueData, data);
   return;
@@ -2829,9 +2859,8 @@ bin_handle_async_start (GstBin * bin, gboolean new_base_time)
   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) {
@@ -2873,8 +2902,8 @@ bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
   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)
@@ -2953,15 +2982,14 @@ bin_handle_async_done (GstBin * bin, GstStateChangeReturn ret,
 
   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. */
@@ -3001,6 +3029,33 @@ nothing_pending:
   }
 }
 
+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
@@ -3109,28 +3164,15 @@ gst_bin_handle_message_func (GstBin * bin, GstMessage * message)
     }
     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:
index 5d8912c4d365ebdcb487692de5d6c8a51a1e578c..6cc673132d6a63e8007a0e88670f1328566c0e4d 100644 (file)
@@ -565,82 +565,6 @@ gst_caps_steal_structure (GstCaps * caps, guint index)
   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
@@ -810,7 +734,7 @@ gst_caps_merge_structure (GstCaps * caps, GstStructure * structure)
     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;
@@ -1117,15 +1036,7 @@ gst_caps_is_equal_fixed (const GstCaps * caps1, const GstCaps * caps2)
   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);
 }
 
 /**
@@ -1162,8 +1073,9 @@ gst_caps_is_always_compatible (const GstCaps * caps1, const GstCaps * caps2)
 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);
@@ -1173,12 +1085,65 @@ gst_caps_is_subset (const GstCaps * subset, const GstCaps * superset)
   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
@@ -1215,127 +1180,6 @@ gst_caps_is_equal (const GstCaps * caps1, const GstCaps * caps2)
 
 /* 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
@@ -1403,7 +1247,7 @@ gst_caps_can_intersect (const GstCaps * caps1, const GstCaps * caps2)
       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 */
@@ -1474,9 +1318,9 @@ gst_caps_intersect_zig_zag (const GstCaps * caps1, const GstCaps * caps2)
       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))
@@ -1533,9 +1377,9 @@ gst_caps_intersect_first (const GstCaps * caps1, const GstCaps * caps2)
     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);
     }
   }
 
index f79939c61af80057c3d8914c9f9b37f440ed2310..b7c5c0fc3a8f2bbe967b3ef004f4826085af0036 100644 (file)
@@ -258,6 +258,8 @@ gboolean          gst_caps_is_always_compatible    (const GstCaps *caps1,
                                                     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,
index 65e9527a4d01b1d4cf4d1c8245ca7845f09b9778..2054aa0298254cad2666194cbd16e71fdc54e3bc 100644 (file)
@@ -391,13 +391,9 @@ gst_child_proxy_set_valist (GstObject * object,
     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;
 
index cc1ed0940b6ebb8a3eac98fda1f4a81a26fd234a..230e19058828908d39efde70be1a6c6b2d146a46 100644 (file)
@@ -205,15 +205,22 @@ G_STMT_START {                                            \
 /**
  * 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) ? \
@@ -407,7 +414,7 @@ typedef enum {
  * @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)
 /**
@@ -430,7 +437,7 @@ struct _GstClock {
   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;
@@ -521,7 +528,7 @@ void                        gst_clock_get_calibration       (GstClock *clock, GstClockTime *internal,
 /* 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);
 
 
index 12fc6fac8a078b3b07fe3b2976ebb00fa09d98ed..ddbba3e409b4008512494992a7d8e00bd09fc1bd 100644 (file)
@@ -2317,6 +2317,28 @@ nothing_aborted:
   }
 }
 
+/* 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.
@@ -2344,7 +2366,6 @@ gst_element_continue_state (GstElement * element, GstStateChangeReturn ret)
   GstStateChangeReturn old_ret;
   GstState old_state, old_next;
   GstState current, next, pending;
-  GstMessage *message;
   GstStateChange transition;
 
   GST_OBJECT_LOCK (element);
@@ -2380,9 +2401,7 @@ gst_element_continue_state (GstElement * element, GstStateChangeReturn ret)
       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",
@@ -2414,16 +2433,9 @@ complete:
      * 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);
 
@@ -2496,9 +2508,7 @@ gst_element_lost_state_full (GstElement * element, gboolean new_base_time)
     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);
@@ -2793,18 +2803,18 @@ invalid_return:
 }
 
 /* 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 */
@@ -2816,8 +2826,7 @@ clear_caps (GstPad * pad, GValue * ret, gboolean * active)
   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,
index 04b5ba820cef8e872940a5275004e80dd441c8fd..74a0e2ce9b628c1753dee94e1fcf6c6e1d0f0cb2 100644 (file)
@@ -85,8 +85,8 @@ G_BEGIN_DECLS
  *                               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,
@@ -195,17 +195,17 @@ typedef enum {
  *     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.
@@ -214,12 +214,12 @@ typedef enum {
  *     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>
@@ -228,15 +228,15 @@ typedef enum {
  *     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.
@@ -245,24 +245,25 @@ typedef enum {
  *     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.
@@ -274,7 +275,7 @@ typedef enum {
  *     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
@@ -602,6 +603,7 @@ struct _GstElement
  * @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.
@@ -669,8 +671,11 @@ struct _GstElementClass
   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 */
index 313759d5a4f0432c688775415b9cadeccba2bee8..4a024a26efb952edd1a42b9c475f90e240c29255 100644 (file)
@@ -73,7 +73,6 @@ struct _GstProxyPadPrivate
 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);
@@ -91,12 +90,26 @@ static void on_src_target_notify (GstPad * target,
 
 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);
@@ -104,12 +117,28 @@ gst_proxy_pad_do_query_type (GstPad * pad)
   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);
@@ -118,12 +147,27 @@ gst_proxy_pad_do_event (GstPad * pad, GstEvent * event)
   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);
@@ -132,28 +176,69 @@ gst_proxy_pad_do_query (GstPad * pad, GstQuery * query)
   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);
@@ -162,58 +247,135 @@ gst_proxy_pad_do_bufferalloc (GstPad * pad, guint64 offset, guint size,
   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);
@@ -256,12 +418,27 @@ done:
   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);
@@ -274,23 +451,52 @@ gst_proxy_pad_do_acceptcaps (GstPad * pad, GstCaps * caps)
   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);
@@ -364,22 +570,46 @@ gst_proxy_pad_get_target (GstPad * pad)
   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;
 
@@ -417,20 +647,20 @@ gst_proxy_pad_class_init (GstProxyPadClass * klass)
   }
 #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
@@ -471,17 +701,17 @@ gst_proxy_pad_init (GstProxyPad * ppad)
       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)
@@ -558,13 +788,26 @@ G_DEFINE_TYPE (GstGhostPad, gst_ghost_pad, GST_TYPE_PROXY_PAD);
 
 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));
 
@@ -576,12 +819,26 @@ gst_ghost_pad_internal_do_activate_push (GstPad * pad, gboolean active)
   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));
 
@@ -589,7 +846,7 @@ gst_ghost_pad_internal_do_activate_pull (GstPad * pad, gboolean active)
     /* 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);
@@ -609,12 +866,25 @@ gst_ghost_pad_internal_do_activate_pull (GstPad * pad, gboolean active)
   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));
 
@@ -625,12 +895,25 @@ gst_ghost_pad_do_activate_push (GstPad * pad, gboolean active)
   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));
 
@@ -656,12 +939,26 @@ gst_ghost_pad_do_activate_pull (GstPad * pad, gboolean active)
   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);
@@ -695,11 +992,21 @@ link_failed:
   }
 }
 
-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");
@@ -792,28 +1099,27 @@ done:
     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
@@ -827,10 +1133,10 @@ gst_ghost_pad_class_init (GstGhostPadClass * klass)
 
   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
@@ -839,13 +1145,12 @@ gst_ghost_pad_init (GstGhostPad * pad)
   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
@@ -862,7 +1167,7 @@ gst_ghost_pad_dispose (GObject * object)
   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))
@@ -926,17 +1231,18 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
 
   /* 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;
@@ -955,13 +1261,15 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
 
   /* 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);
@@ -993,9 +1301,9 @@ gst_ghost_pad_construct (GstGhostPad * gpad)
 
   /* 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);
 
index f492a74b59973a51c66a52112ceb5c24ce09b78a..308ab70cb65f17f6e059efa2ebccab0b54c82d2e 100644 (file)
@@ -59,6 +59,23 @@ struct _GstProxyPadClass
 
 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))
@@ -106,6 +123,15 @@ gboolean    gst_ghost_pad_set_target       (GstGhostPad *gpad, GstPad *newtarget);
 
 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__ */
index 0eafac52df185c7ed6741e1f5aa88644404f7375..757b1d5bed9c63d7460be5c554ac6fdcdcf38ec6 100644 (file)
@@ -74,11 +74,11 @@ typedef struct _GstMessageClass GstMessageClass;
  * @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
index 4b46d292977749dc450d15803b46ed98e071faef..3993e02a718ca47984506d9485ad0ce2a8b0ec8b 100644 (file)
@@ -46,6 +46,24 @@ static GstAllocTrace *_gst_mini_object_trace;
 #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);
@@ -55,6 +73,7 @@ static void gst_mini_object_init (GTypeInstance * instance, gpointer klass);
 
 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);
@@ -66,6 +85,9 @@ static gchar *gst_value_mini_object_lcopy (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)
 {
@@ -138,6 +160,9 @@ gst_mini_object_class_init (gpointer g_class, gpointer class_data)
 
   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
@@ -146,6 +171,9 @@ gst_mini_object_init (GTypeInstance * instance, gpointer klass)
   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 *
@@ -320,6 +348,16 @@ gst_mini_object_ref (GstMiniObject * mini_object)
   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)
 {
@@ -340,6 +378,10 @@ 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
@@ -370,6 +412,109 @@ gst_mini_object_unref (GstMiniObject * mini_object)
   }
 }
 
+/**
+ * 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
@@ -427,8 +572,8 @@ gst_value_mini_object_copy (const GValue * src_value, GValue * dest_value)
 {
   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;
   }
@@ -556,8 +701,8 @@ gst_value_dup_mini_object (const GValue * value)
 {
   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;
 }
 
 
index 1005dc544253f968e5eb5fa1ea04b072230ae87b..024d1e21111f529925e8b08ba8d483fe3df5aaab 100644 (file)
@@ -135,6 +135,25 @@ typedef enum
  */
 #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
@@ -154,7 +173,7 @@ struct _GstMiniObject {
   guint flags;
 
   /*< private >*/
-  gpointer _gst_reserved;
+  GstMiniObjectPrivate *priv;
 };
 
 struct _GstMiniObjectClass {
@@ -177,6 +196,12 @@ GstMiniObject*  gst_mini_object_make_writable      (GstMiniObject *mini_object);
 /* 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 */
index c18448540e4653743dc33d1c09040742f23c1948..14c97863ef6371a53d9e5a6896d39fee6d8a5039 100644 (file)
@@ -1132,7 +1132,7 @@ had_right_state:
  * 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.
@@ -2022,7 +2022,7 @@ no_format:
  * @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.
  */
@@ -3287,7 +3287,7 @@ gst_pad_iterate_internal_links_default (GstPad * pad)
      * 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");
@@ -3398,7 +3398,7 @@ add_unref_pad_to_list (GstPad * pad, GList ** list)
  * 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
@@ -3490,11 +3490,11 @@ no_parent:
  *
  * 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
@@ -3511,7 +3511,7 @@ gst_pad_get_internal_links (GstPad * pad)
   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;
 }
@@ -3570,8 +3570,9 @@ gst_pad_event_default_dispatch (GstPad * pad, GstEvent * event)
         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:
index 19834c41d39cecfd2674102a8edc29ca474057d5..5317dee41c341c5273019bd9d7fa9f7b01a9f884 100644 (file)
@@ -192,7 +192,7 @@ GQuark                      gst_flow_to_quark       (GstFlowReturn ret);
  * @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.
@@ -223,7 +223,7 @@ typedef enum {
 /**
  * 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
@@ -405,7 +405,10 @@ typedef gboolean           (*GstPadCheckGetRangeFunction)  (GstPad *pad);
  *
  * Deprecated: use the threadsafe #GstPadIterIntLinkFunction instead.
  */
+#ifndef GST_DISABLE_DEPRECATED
 typedef GList*                 (*GstPadIntLinkFunction)        (GstPad *pad);
+#endif
+
 
 /**
  * GstPadIterIntLinkFunction:
@@ -708,7 +711,13 @@ struct _GstPad {
   GstPadQueryFunction           queryfunc;
 
   /* internal links */
+#ifndef GST_DISABLE_DEPRECATED
   GstPadIntLinkFunction                 intlinkfunc;
+#else
+#ifndef __GTK_DOC_IGNORE__
+  gpointer intlinkfunc;
+#endif
+#endif
 
   GstPadBufferAllocFunction      bufferallocfunc;
 
index 3c62b1b08e908c0e16c7117af74672235e94090c..c72a1f77800db59f4ffb92055c5e120079d1d5da 100644 (file)
@@ -65,7 +65,6 @@ gst_plugin_feature_finalize (GObject * object)
 
   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,
@@ -85,7 +84,7 @@ gst_plugin_feature_finalize (GObject * object)
  * 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);
@@ -184,12 +183,12 @@ gst_plugin_feature_set_name (GstPluginFeature * feature, const gchar * name)
   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);
 }
 
 /**
index 177c8bd3a3887c89517d24d782d97d90c1c8ccad..baf592c8a7732b1b6a02f386da53ca75342c7757 100644 (file)
@@ -81,7 +81,7 @@ struct _GstPluginFeature {
 
   /*< private >*/
   gboolean       loaded;
-  gchar         *name;
+  gchar         *name; /* FIXME-0.11: remove variable, we use GstObject:name */
   guint          rank;
 
   const gchar   *plugin_name;
index d566065734890aaeb7759091e2e927cac9c61768..811e4d18612692c40149569e459a39dbca06471b 100644 (file)
@@ -86,6 +86,8 @@
 #include "gst_private.h"
 
 #include "gstpreset.h"
+#include "gstinfo.h"
+#include "gstvalue.h"
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -253,12 +255,13 @@ wrong_name:
 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, &micro, &nano);
+  num = sscanf (str_version, "%u.%u.%u.%u", &major, &minor, &micro, &nano);
   /* make sure we have atleast "major.minor" */
   if (num > 1) {
     guint64 version;
index 73816326bd0fb8dc5052eaf2c37b0f8f0a3a79b0..ccf1366f66b5d747dc32670a1300b979a94069f3 100644 (file)
@@ -23,7 +23,6 @@
 #define __GST_PRESET_H__
 
 #include <glib-object.h>
-#include <gst/gst.h>
 
 G_BEGIN_DECLS
 
index 5b6df92f3b539cb5ab4a47fbe92b785e9c389513..0955ae1621143cd1967a490e1428670412ab1277 100644 (file)
@@ -46,7 +46,7 @@
  * 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:
@@ -280,7 +280,7 @@ gst_registry_finalize (GObject * object)
     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);
   }
@@ -485,7 +485,7 @@ gst_registry_remove_features_for_plugin_unlocked (GstRegistry * registry,
 
       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;
   }
@@ -561,10 +561,10 @@ gst_registry_add_feature (GstRegistry * registry, GstPluginFeature * feature)
   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)
@@ -55,12 +55,12 @@ G_BEGIN_DECLS
  * 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)
@@ -532,8 +532,9 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
   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;
 
@@ -548,7 +549,7 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
   }
 
   /* 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);
@@ -556,16 +557,13 @@ gst_registry_chunks_load_feature (GstRegistry * registry, gchar ** in,
   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);
index f0ff914fefaf308c9632ac03d83bb2fbee17a1c3..3b2c2e41216e65f68adec17379cf38ce77bd9378 100644 (file)
@@ -565,12 +565,7 @@ gst_structure_set_valist_internal (GstStructure * structure,
       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);
+}
index 57e34c0f714c7229ea7c1527e6bdee6a431c18ec..6e020fce33886d3b704446a4e7be7b8fd9421726 100644 (file)
@@ -248,6 +248,15 @@ gboolean                 gst_structure_fixate_field_nearest_fraction (GstStructu
                                                                         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
index 7ada0c952bba9a69b7a5c155b362f3edee6785cf..938704e544cb8f24f9609c57e18dc24ed3b581ef 100644 (file)
@@ -328,9 +328,16 @@ gst_system_clock_add_wakeup (GstSystemClock * sysclock)
   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++;
index 7022b26ab11e563a989214c7be689bf94de3f2c5..385e3b019811340330eaafa24c298e691082edad 100644 (file)
@@ -1011,12 +1011,7 @@ gst_tag_list_add_valist (GstTagList * list, GstTagMergeMode mode,
       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);
index 8baf1e6150734ff041e50fb371b6b174343299cb..381716094120d92db051f1017fbd21406ecdbbdf 100644 (file)
@@ -3394,10 +3394,28 @@ gint
 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;
 
index 7e834048f2c6363872c13a9446540599fe013125..30abeb3715f205348b9e1d6a677a4f7585290c47 100644 (file)
@@ -45,6 +45,8 @@ lex._gst_parse_yy.c: parse.l grammar.tab.h
        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
index 7e8b9944552b0ec4c0460da49062dab27a300eab..db1f585646c5e4e81e4b0b16f2257c61a23dfee9 100644 (file)
@@ -69,17 +69,24 @@ static inline void
 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>
@@ -237,6 +241,7 @@ struct _GstBaseParsePrivate
   guint bitrate;
   guint lead_in, lead_out;
   GstClockTime lead_in_ts, lead_out_ts;
+  GstClockTime min_latency, max_latency;
 
   gboolean discont;
   gboolean flushing;
@@ -306,6 +311,9 @@ struct _GstBaseParsePrivate
 
   /* Segment event that closes the running segment prior to SEEK */
   GstEvent *close_segment;
+
+  /* push mode helper frame */
+  GstBaseParseFrame frame;
 };
 
 typedef struct _GstBaseParseSeek
@@ -566,8 +574,11 @@ gst_base_parse_frame_free (GstBaseParseFrame * frame)
     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
@@ -720,6 +731,11 @@ gst_base_parse_reset (GstBaseParse * parse)
   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);
 }
 
@@ -1023,6 +1039,9 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
       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:
@@ -2157,19 +2176,17 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
   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);
     }
@@ -2186,16 +2203,29 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
     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);
 
@@ -2224,7 +2254,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
       /* 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);
 
@@ -2497,6 +2527,12 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
   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;
 
@@ -2547,7 +2583,9 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
       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;
@@ -3018,6 +3056,31 @@ gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough)
   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)
@@ -3178,6 +3241,29 @@ gst_base_parse_query (GstPad * pad, GstQuery * query)
       }
       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)
@@ -297,6 +297,10 @@ void            gst_base_parse_set_frame_rate  (GstBaseParse * parse,
                                                 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)
@@ -2186,14 +2186,21 @@ gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
   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
@@ -3229,7 +3236,7 @@ stopping:
  *
  * 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)
@@ -234,6 +234,7 @@ struct _GstBaseSrcPrivate
   GstClockTimeDiff ts_offset;
 
   gboolean do_timestamp;
+  volatile gint dynamic_size;
 
   /* stream sequence number */
   guint32 seqnum;
@@ -323,6 +324,8 @@ static GstFlowReturn gst_base_src_pad_get_range (GstPad * pad, guint64 offset,
 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)
@@ -584,6 +587,25 @@ gst_base_src_set_format (GstBaseSrc * src, GstFormat format)
   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
@@ -932,9 +954,14 @@ gst_base_src_default_query (GstBaseSrc * src, GstQuery * query)
         {
           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);
@@ -2028,6 +2055,7 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length)
   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)
@@ -245,6 +245,8 @@ gboolean        gst_base_src_is_live          (GstBaseSrc *src);
 
 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)
@@ -654,26 +654,25 @@ gst_base_transform_getcaps (GstPad * pad)
 {
   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,
@@ -690,8 +689,16 @@ gst_base_transform_getcaps (GstPad * pad)
     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));
@@ -700,6 +707,9 @@ gst_base_transform_getcaps (GstPad * pad)
 done:
   GST_DEBUG_OBJECT (trans, "returning  %" GST_PTR_FORMAT, caps);
 
+  if (peercaps)
+    gst_caps_unref (peercaps);
+
   gst_object_unref (trans);
 
   return caps;
@@ -853,7 +863,9 @@ gst_base_transform_find_transform (GstBaseTransform * trans, GstPad * pad,
     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;
@@ -1787,7 +1799,9 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
         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;
@@ -1802,7 +1816,9 @@ gst_base_transform_buffer_alloc (GstPad * pad, guint64 offset, guint size,
 
           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)
@@ -146,6 +146,34 @@ G_STMT_START {                                                             \
  */
 #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)
@@ -275,6 +275,8 @@ gst_fd_src_update_fd (GstFdSrc * src, guint64 size)
 
     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;
 
@@ -282,6 +284,7 @@ not_seekable:
   {
     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)
@@ -1019,6 +1019,8 @@ gst_file_src_start (GstBaseSrc * basesrc)
    * 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)
@@ -95,9 +95,12 @@ enum
 {
   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
@@ -624,6 +627,105 @@ gst_input_selector_wait (GstInputSelector * self, GstSelectorPad * pad)
   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)
 {
@@ -651,6 +753,16 @@ 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)) {
@@ -669,6 +781,10 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
   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;
 
@@ -899,6 +1015,21 @@ gst_input_selector_class_init (GstInputSelectorClass * klass)
           "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
@@ -991,6 +1122,7 @@ gst_input_selector_init (GstInputSelector * sel,
   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 ();
@@ -1105,6 +1237,12 @@ gst_input_selector_set_active_pad (GstInputSelector * self,
 
   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);
 
@@ -1130,6 +1268,13 @@ gst_input_selector_set_property (GObject * object, guint prop_id,
       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;
@@ -1153,6 +1298,11 @@ gst_input_selector_get_property (GObject * object, guint prop_id,
       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)
@@ -56,6 +56,7 @@ struct _GstInputSelector {
   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)
@@ -157,6 +157,8 @@ struct _GstSingleQueue
   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 */
 };
 
@@ -180,6 +182,7 @@ static void gst_single_queue_free (GstSingleQueue * squeue);
 
 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);
 
@@ -225,6 +228,7 @@ enum
 #define DEFAULT_USE_BUFFERING FALSE
 #define DEFAULT_LOW_PERCENT   10
 #define DEFAULT_HIGH_PERCENT  99
+#define DEFAULT_SYNC_BY_RUNNING_TIME FALSE
 
 enum
 {
@@ -238,6 +242,7 @@ enum
   PROP_USE_BUFFERING,
   PROP_LOW_PERCENT,
   PROP_HIGH_PERCENT,
+  PROP_SYNC_BY_RUNNING_TIME,
   PROP_LAST
 };
 
@@ -397,6 +402,22 @@ gst_multi_queue_class_init (GstMultiQueueClass * klass)
           "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;
 
@@ -426,8 +447,11 @@ gst_multi_queue_init (GstMultiQueue * mqueue, GstMultiQueueClass * klass)
   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 ();
 }
@@ -500,6 +524,9 @@ gst_multi_queue_set_property (GObject * object, guint prop_id,
     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;
@@ -542,6 +569,9 @@ gst_multi_queue_get_property (GObject * object, guint prop_id,
     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);
@@ -947,6 +984,71 @@ apply_buffer (GstMultiQueue * mq, GstSingleQueue * sq, GstClockTime timestamp,
   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)
@@ -1079,6 +1181,7 @@ gst_multi_queue_loop (GstPad * pad)
   GstMiniObject *object = NULL;
   guint32 newid;
   GstFlowReturn result;
+  GstClockTime next_time;
 
   sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
   mq = sq->mqueue;
@@ -1100,6 +1203,9 @@ gst_multi_queue_loop (GstPad * pad)
   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);
 
@@ -1108,9 +1214,9 @@ gst_multi_queue_loop (GstPad * pad)
    * 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));
 
@@ -1125,6 +1231,7 @@ gst_multi_queue_loop (GstPad * pad)
 
     /* 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)
@@ -1135,10 +1242,20 @@ gst_multi_queue_loop (GstPad * pad)
 
       /* 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);
@@ -1152,8 +1269,13 @@ gst_multi_queue_loop (GstPad * pad)
           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 */
@@ -1163,8 +1285,9 @@ gst_multi_queue_loop (GstPad * pad)
       /* 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);
   }
@@ -1175,6 +1298,18 @@ gst_multi_queue_loop (GstPad * pad)
   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;
@@ -1188,6 +1323,7 @@ gst_multi_queue_loop (GstPad * pad)
       gst_flow_get_name (sq->srcresult));
 
   sq->last_oldid = newid;
+
   return;
 
 out_flushing:
@@ -1517,7 +1653,10 @@ wake_up_next_non_linked (GstMultiQueue * mq)
     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);
       }
@@ -1568,6 +1707,49 @@ compute_high_id (GstMultiQueue * mq)
       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))
 
@@ -1771,6 +1953,8 @@ gst_single_queue_new (GstMultiQueue * mqueue, gint id)
 
   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)
@@ -50,6 +50,8 @@ typedef struct _GstMultiQueueClass GstMultiQueueClass;
 struct _GstMultiQueue {
   GstElement element;
 
+  gboolean sync_by_running_time;
+
   /* number of queues */
   guint        nbqueues;
 
@@ -65,6 +67,7 @@ struct _GstMultiQueue {
 
   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)
@@ -371,7 +371,6 @@ gst_output_selector_buffer_alloc (GstPad * pad, guint64 offset, guint size,
   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)
@@ -898,6 +898,7 @@ reset_rate_timer (GstQueue2 * queue)
   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;
@@ -910,8 +911,11 @@ reset_rate_timer (GstQueue2 * queue)
 /* 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
@@ -933,14 +937,20 @@ update_in_rates (GstQueue2 * queue)
     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)
@@ -116,6 +116,7 @@ struct _GstQueue2
   gdouble last_in_elapsed;
   guint64 bytes_in;
   gdouble byte_in_rate;
+  gdouble byte_in_period;
 
   GTimer *out_timer;
   gboolean out_timer_started;
index a181e82b61858c4970ad67c7c9411d4225bd3cc8..dfd93b85b37a9678d702aa9ef0eeed606932313b 100644 (file)
--- a/po/af.po
+++ b/po/af.po
@@ -7,7 +7,7 @@ msgid ""
 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"
@@ -1128,6 +1128,10 @@ msgstr ""
 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)"
 
index 4ce2582aa7149e5134bda470a7972e27a2829a37..c022a6be8c8559ec40639ae87d858e3b20745e07 100644 (file)
--- a/po/az.po
+++ b/po/az.po
@@ -7,7 +7,7 @@ msgid ""
 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"
@@ -1075,6 +1075,10 @@ msgstr ""
 msgid "Interrupt: Stopping pipeline ...\n"
 msgstr ""
 
+#, c-format
+msgid "Missing element: %s\n"
+msgstr ""
+
 msgid "Output tags (also known as metadata)"
 msgstr ""
 
index dbd76abf8b015b97b6075f75de766ab53cecf409..6da856d2bb67f222e03a9614c571dadace700d33 100644 (file)
--- a/po/be.po
+++ b/po/be.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1084,6 +1084,10 @@ msgstr ""
 msgid "Interrupt: Stopping pipeline ...\n"
 msgstr ""
 
+#, c-format
+msgid "Missing element: %s\n"
+msgstr ""
+
 msgid "Output tags (also known as metadata)"
 msgstr ""
 
index 4c9489d0687f4c94f8a83c0846102af9c3d27f43..29d96ef67bbca8875e1d8f7ad24d09ba058f5c95 100644 (file)
--- a/po/bg.po
+++ b/po/bg.po
@@ -8,7 +8,7 @@ msgid ""
 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"
@@ -1126,6 +1126,10 @@ msgstr "Задаване на състоянието на %s по заявка 
 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 "Изходни съобщения за етикетите (метаданните)"
 
index 0edb1bfb95381f12244198e35d9dbce38e49bdc1..bebce39be1ed3847c9a96fa67864b971d95dd9a1 100644 (file)
--- a/po/ca.po
+++ b/po/ca.po
@@ -7,7 +7,7 @@ msgid ""
 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"
@@ -1132,6 +1132,10 @@ msgstr "S'està establint l'estat a %s a petició de %s…\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)"
 
index 4e42da628eceea19628bfe9626e5587682f0c8ca..19176b4555019eab742f140217988b414222217a 100644 (file)
--- a/po/cs.po
+++ b/po/cs.po
@@ -8,7 +8,7 @@ msgid ""
 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"
@@ -1140,6 +1140,10 @@ msgstr ""
 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)"
 
index 813661a6d9f203d7ab1df2b70c762d1d406eae6b..f9bdaf843446d19e2f99787f4f220b3fedc57f95 100644 (file)
--- a/po/da.po
+++ b/po/da.po
@@ -8,7 +8,7 @@ msgid ""
 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"
@@ -1127,6 +1127,10 @@ msgstr "Sætter tilstand til %s som krævet af %s...\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)"
 
index cc8741a0c4086ef334984ad2f36d47109b5035fa..36f8ae4138881620bfdf1a36f44d59b36341b6e3 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -9,7 +9,7 @@ msgid ""
 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"
@@ -1149,6 +1149,10 @@ msgstr "Status wird auf %s gesetzt wie von %s gewünscht...\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"
 
index c4409ca7bf7d08cc252c69816663b8959be30462..f2585be49a4b9f083c4da582f16befdd3b04419e 100644 (file)
--- a/po/el.po
+++ b/po/el.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1142,6 +1142,10 @@ msgstr "Ορισμός κατάστασης σε %s όπως ζητήθηκε α
 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 "Ετικέτες εξόδου (επίσης γνωστές ως μεταδεδομένα)"
 
index f77ab29856bb1d23eccf63cf972af6f655f03712..fd70295d38435b660c31b0d6e9c95120cb6a1ffa 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1132,6 +1132,10 @@ msgstr ""
 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)"
 
index c579819a8848cf42b2f354e9fddfe9d4ffa5a4a7..84e17719b5115d9c697232b11b3e513efbb4aec9 100644 (file)
--- a/po/es.po
+++ b/po/es.po
@@ -7,7 +7,7 @@ msgid ""
 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"
@@ -1138,6 +1138,10 @@ msgstr "Estableciendo el estado a %s según lo solicitó %s…\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)"
 
index 529077fb5dc0f5c1372a150c27f16ddfb7a21b1a..ddd431a7b514e66cf24ad35011a3d129d93d9c89 100644 (file)
--- a/po/eu.po
+++ b/po/eu.po
@@ -8,7 +8,7 @@ msgid ""
 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"
@@ -1134,6 +1134,10 @@ msgstr "Egoera %s(e)ra ezartzen %s(e)k eskatu bezala...\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)"
 
index 1add3ba935eebdbb821d09ee0016a9d847d8e5dd..0f77f4d01c64c0a55bb74449c15b75c41638de1d 100644 (file)
--- a/po/fi.po
+++ b/po/fi.po
@@ -12,7 +12,7 @@ msgid ""
 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"
@@ -1125,6 +1125,10 @@ msgstr "Asetetaan tilaan %s kuten %s pyysi...\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)"
 
index 9641e7779ebfca06f4f6f4bab79000ff7db9e721..b4adae0ba6f653474494a9b14b00b1d8ec89a503 100644 (file)
--- a/po/fr.po
+++ b/po/fr.po
@@ -9,7 +9,7 @@ msgid ""
 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"
@@ -1133,6 +1133,10 @@ msgstr "Définition de l'état à %s comme demandé par %s...\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)"
 
index a58aec8ac23faa4d0cf6a5dd4a02fbb3cb95c736..f456f8f4869a7914f3a4c08791faad3a655ba76d 100644 (file)
--- a/po/gl.po
+++ b/po/gl.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1126,6 +1126,10 @@ msgstr "Estabelecendo o estado a %s segundo foi solicitado por %s...\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)"
 
index 74b2fd76f13a97b6fe5310afa342b2a4c94ce1a0..ebe852157b028806aab0d2a4de021dc51f39ac99 100644 (file)
--- a/po/hu.po
+++ b/po/hu.po
@@ -7,7 +7,7 @@ msgid ""
 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"
@@ -1117,6 +1117,10 @@ msgstr "Állapot beállítása erre: %s, %s kérésének megfelelően…\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)"
 
index ea40ed1338f22df2521c7b84efba55eb1589faae..9b88775bd57bdea991e10de1d23ecf3e8ca31d9f 100644 (file)
--- a/po/id.po
+++ b/po/id.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1124,6 +1124,10 @@ msgstr "Mengatur tingkat ke %s seperti diminta oleh %s...\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)"
 
index c48f6706f9e6905a5b03d635acf7079584ddcf97..f26d74054cec3ef29c515edf0c10b934c3816322 100644 (file)
--- a/po/it.po
+++ b/po/it.po
@@ -106,7 +106,7 @@ msgid ""
 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"
@@ -1294,6 +1294,10 @@ msgstr "Impostazione dello stato a %s come richiesto da %s...\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)"
index dc0d8c55bd06c6a097abe1c91fb97ee39a0c5692..6cab73a70c80e6cb8183a07dad5d4fb6907e6c76 100644 (file)
--- a/po/ja.po
+++ b/po/ja.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1102,6 +1102,10 @@ msgstr ""
 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 "タグ (メタデータ) を出力する"
 
index 119cf67ef21f17f8015f82e2eaecca741ef1864b..0ea69f54794bb103ba510f58a7641acf39702404 100644 (file)
--- a/po/lt.po
+++ b/po/lt.po
@@ -7,7 +7,7 @@ msgid ""
 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"
@@ -1128,6 +1128,10 @@ msgstr "Nustatoma būsena į %s, kaip prašė %s...\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)"
 
index 0fd1f5bb31706d57d9283db881e023f449ee4500..c9d96c98fbbcdf31b4d7517963540da06e2dcf94 100644 (file)
--- a/po/nb.po
+++ b/po/nb.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1087,6 +1087,10 @@ msgstr ""
 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 ""
 
index 65965491ea3da1c72d4c2fa30417fa6984fea0a1..03852216c8bdfdca8086ca2f10e2a36e015df7f5 100644 (file)
--- a/po/nl.po
+++ b/po/nl.po
@@ -10,7 +10,7 @@ msgid ""
 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"
@@ -1134,6 +1134,10 @@ msgstr "Stel de status in op %s zoals verzocht door %s...\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"
 
index aa1e2db30f55a7ea61650e218128f174ebfb17dd..f49bb2237297f53b9e33e9267855035d25616dd1 100644 (file)
--- a/po/pl.po
+++ b/po/pl.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1128,6 +1128,10 @@ msgstr "Ustawianie stanu na %s zgodnie z wymaganiem %s...\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)"
 
index d144759925bf21ab7e88d306986305f911b0348a..4a59558b9b930defbcc98083f8d361eee4d13f2c 100644 (file)
@@ -17,7 +17,7 @@ msgid ""
 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"
@@ -1144,6 +1144,10 @@ msgstr "Definindo estado de %s como requerido por %s...\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)"
 
index e7e7e3f966d47dcfc4afcfce12a79ed28939c14f..ab39aac88f0ec5691a912754fd0a28861c084d99 100644 (file)
--- a/po/ro.po
+++ b/po/ro.po
@@ -5,7 +5,7 @@ msgid ""
 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"
@@ -1150,6 +1150,10 @@ msgstr "Se definește starea la %s după cum a fost cerut de %s...\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”)"
 
index 2300900452d2fd0cdf5354b9e9e2f83d9fcdd2d2..0144f7cbd33f1a030d6e1bfe04251416fb4e8301 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -9,7 +9,7 @@ msgid ""
 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"
@@ -1128,6 +1128,10 @@ msgstr "Устанавливается состояние %s, запрошенн
 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 "Выводить теги (метаданные)"
 
index 6200b2fcf573b4c4a817b7977609e7f19efeee69..7178bad144e5c494ace64f0c14700a921cd3b9b0 100644 (file)
--- a/po/rw.po
+++ b/po/rw.po
@@ -15,7 +15,7 @@ msgid ""
 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"
@@ -1303,6 +1303,10 @@ msgstr ""
 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"
index 7c266a1fbba9e6cb6564a7c16fb044c8b4af819e..f818a54e51589ac5b47db0d0cbe82eb7c5291a63 100644 (file)
--- a/po/sk.po
+++ b/po/sk.po
@@ -8,7 +8,7 @@ msgid ""
 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"
@@ -1140,6 +1140,10 @@ msgstr "Nastavujem stav na %s ako požaduje %s...\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)"
 
index 20996f530c291197da3466cf5d6a503091817961..7f1fe7f44060b9ecb75d2e6f8521abc97a222e5f 100644 (file)
--- a/po/sl.po
+++ b/po/sl.po
@@ -8,7 +8,7 @@ msgid ""
 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"
@@ -1124,6 +1124,10 @@ msgstr "Nastavljanje stanja na %s, kot to zahteva %s ...\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 ""
 
index 2b35a2341483823a30071a175e3170f722e2697d..dbc2ffa7507f7e63dc7d7b844d9601f7dadb2949 100644 (file)
--- a/po/sq.po
+++ b/po/sq.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1138,6 +1138,10 @@ msgstr ""
 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)"
 
index 272ed70beda74449ab44053678f675d1368190f3..82810fb59a84f9a188f5e0504f1d0acaa2cb1a93 100644 (file)
--- a/po/sr.po
+++ b/po/sr.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1152,6 +1152,10 @@ msgstr ""
 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 adbde5621722a5351fb408b1caa1aac20ec57113..d27e686961a8da4c9c314011b5482fe712177e4e 100644 (file)
--- a/po/sv.po
+++ b/po/sv.po
@@ -8,7 +8,7 @@ msgid ""
 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"
@@ -1135,6 +1135,10 @@ msgstr "Ställer in tillståndet till %s enligt begäran från %s...\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)"
 
index a4c2a40c8f4a08b87e3698a9e7b028a5df62e1a2..d973ac9baeaf1e918f6926c454433b0f2f28943e 100644 (file)
--- a/po/tr.po
+++ b/po/tr.po
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1138,6 +1138,10 @@ msgstr ""
 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)"
 
index 50b36d9c7d02491a01f5ff603e65dce8bab09e0a..70d9a32b5405827e0a8f084e82fa75981846878d 100644 (file)
--- a/po/uk.po
+++ b/po/uk.po
@@ -7,7 +7,7 @@ msgid ""
 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"
@@ -1131,6 +1131,10 @@ msgstr ""
 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 "Вивести теги (також відомі як метадані)"
 
index d95c7a04cc0c9e6b0449bd88c6767f219c975d25..6dafb70c78af5983a01e82af8791d3f38b6100ba 100644 (file)
--- a/po/vi.po
+++ b/po/vi.po
@@ -7,7 +7,7 @@ msgid ""
 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"
@@ -1125,6 +1125,10 @@ msgstr "Đang đặt tình trạng thành %s như yêu cầu bởi %s....\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)"
 
index daaf2027bd2cad09761b81a9c289ff67c40bc814..92a1d9e41e6dc1cadcafda45115b9992dfee7220 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1096,6 +1096,10 @@ msgstr "%2$s 发起请求时状态设置为 %1$s...\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 "输出标识(也可认为是元数据)"
 
index 4a83e2121446b83b6b47c6c6040d4ec0272d21ba..7bb8fee216f01aa1cf83f5846de921128daceae5 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 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"
@@ -1115,6 +1115,10 @@ msgstr ""
 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)
@@ -348,6 +348,46 @@ GST_START_TEST (test_truncate)
 
 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;
@@ -573,6 +613,26 @@ GST_START_TEST (test_merge_subset)
   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;
@@ -811,6 +871,24 @@ GST_START_TEST (test_intersect_first2)
 
 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)
@@ -913,6 +991,7 @@ gst_caps_suite (void)
   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);
@@ -921,6 +1000,7 @@ gst_caps_suite (void)
   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)
@@ -255,7 +255,7 @@ GST_END_TEST;
 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);
@@ -278,6 +278,14 @@ GST_START_TEST (test_link)
 
   /* 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)
@@ -175,6 +175,33 @@ GST_START_TEST (test_unref_threaded)
 
 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;
@@ -479,6 +506,7 @@ gst_mini_object_suite (void)
   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)
@@ -67,7 +67,9 @@ GstCheckABIStruct list[] = {
   {"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)
@@ -145,6 +145,8 @@ GST_END_TEST;
 #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)
 {
@@ -285,6 +287,19 @@ 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)
@@ -18,8 +18,6 @@ TESTS_ENVIRONMENT = \
         GST_PLUGIN_SYSTEM_PATH=                                 \
         GST_PLUGIN_PATH=$(top_builddir)/plugins
 
-CLEANFILES = core core.* test-registry.* *.gcno *.gcda
-
 EXTRA_DIST = extract.pl
 
 EXAMPLES = \
@@ -42,53 +40,53 @@ 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 \
index c86285e68af594c0c30e3c3ed87228cab94f70bf..c8f51e5dd4009c8d47104a04fb2caa0c5bba5dd8 100644 (file)
@@ -306,7 +306,7 @@ flags_to_string (GFlagsValue * vals, guint flags)
     --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)
index 2b0d86245e6240d02a33340ed1642aaecd7b98dc..ea99b8f6dda038e61d33b7d8987041dcf1e824d5 100644 (file)
@@ -403,6 +403,24 @@ print_index_stats (GPtrArray * index_stats)
   }
 }
 
+/* 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)
 {
@@ -821,6 +839,16 @@ event_loop (GstElement * pipeline, gboolean blocking, GstState target_state)
           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 */
index 28185bbcfd855783deabb90d5fd0390170207d2c..af2c8e5d1423ab953a0d2427914f3018390b1043 100644 (file)
 #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)
@@ -64,7 +64,7 @@ G_BEGIN_DECLS
  * 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)
@@ -26,6 +26,7 @@ EXPORTS
        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
@@ -63,6 +64,7 @@ EXPORTS
        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)
@@ -172,6 +172,7 @@ EXPORTS
        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
@@ -444,14 +445,21 @@ EXPORTS
        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
@@ -601,6 +609,8 @@ EXPORTS
        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
@@ -832,7 +842,22 @@ EXPORTS
        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
@@ -940,6 +965,7 @@ EXPORTS
        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
@@ -983,6 +1009,9 @@ EXPORTS
        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