aboutsummaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2014-06-22 17:16:06 +0200
committerSebastian Dröge <sebastian@centricular.com>2014-06-22 17:16:06 +0200
commit5254e8378f4c28705a571d7bfbbad5fbd1adb3d3 (patch)
tree3f6cac985731dee5f68347ea99ad30ed19462168 /libs
parent1adbba7bfff7853fca8b02aec57dbe1850d4a55c (diff)
Imported Upstream version 1.3.3
Diffstat (limited to 'libs')
-rw-r--r--libs/Makefile.in1
-rw-r--r--libs/gst/Makefile.in1
-rw-r--r--libs/gst/base/Makefile.am4
-rw-r--r--libs/gst/base/Makefile.in14
-rw-r--r--libs/gst/base/base.h1
-rw-r--r--libs/gst/base/gstadapter.c72
-rw-r--r--libs/gst/base/gstadapter.h2
-rw-r--r--libs/gst/base/gstbaseparse.c65
-rw-r--r--libs/gst/base/gstbaseparse.h2
-rw-r--r--libs/gst/base/gstbasesink.c181
-rw-r--r--libs/gst/base/gstbasesink.h2
-rw-r--r--libs/gst/base/gstbasesrc.c242
-rw-r--r--libs/gst/base/gstbasesrc.h41
-rw-r--r--libs/gst/base/gstbasetransform.c75
-rw-r--r--libs/gst/base/gstbasetransform.h12
-rw-r--r--libs/gst/base/gstbytereader.c36
-rw-r--r--libs/gst/base/gstbytereader.h13
-rw-r--r--libs/gst/base/gstbytewriter-docs.h5
-rw-r--r--libs/gst/base/gstbytewriter.c4
-rw-r--r--libs/gst/base/gstcollectpads.c258
-rw-r--r--libs/gst/base/gstcollectpads.h42
-rw-r--r--libs/gst/base/gstdataqueue.c57
-rw-r--r--libs/gst/base/gstdataqueue.h6
-rw-r--r--libs/gst/base/gstflowcombiner.c248
-rw-r--r--libs/gst/base/gstflowcombiner.h58
-rw-r--r--libs/gst/base/gstindex.c20
-rw-r--r--libs/gst/base/gstpushsrc.c2
-rw-r--r--libs/gst/base/gstqueuearray.c26
-rw-r--r--libs/gst/base/gsttypefindhelper.c36
-rw-r--r--libs/gst/base/gsttypefindhelper.h2
-rw-r--r--libs/gst/check/Makefile.am12
-rw-r--r--libs/gst/check/Makefile.in12
-rw-r--r--libs/gst/check/gstcheck.c121
-rw-r--r--libs/gst/check/gstcheck.h20
-rw-r--r--libs/gst/check/gsttestclock.c209
-rw-r--r--libs/gst/check/gsttestclock.h25
-rw-r--r--libs/gst/check/libcheck/Makefile.in1
-rw-r--r--libs/gst/check/libcheck/check.c2
-rw-r--r--libs/gst/controller/Makefile.am2
-rw-r--r--libs/gst/controller/Makefile.in3
-rw-r--r--libs/gst/controller/gstinterpolationcontrolsource.c2
-rw-r--r--libs/gst/controller/gsttimedvaluecontrolsource.c2
-rw-r--r--libs/gst/helpers/Makefile.in1
-rw-r--r--libs/gst/net/Makefile.am2
-rw-r--r--libs/gst/net/Makefile.in3
-rw-r--r--libs/gst/net/gstnetaddressmeta.c2
-rw-r--r--libs/gst/net/gstnetclientclock.c90
-rw-r--r--libs/gst/net/gstnetclientclock.h2
-rw-r--r--libs/gst/net/gstnettimepacket.c4
-rw-r--r--libs/gst/net/gstnettimeprovider.c8
50 files changed, 1558 insertions, 493 deletions
diff --git a/libs/Makefile.in b/libs/Makefile.in
index 2f00606..b19c609 100644
--- a/libs/Makefile.in
+++ b/libs/Makefile.in
@@ -86,7 +86,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/as-compiler-flag.m4 \
$(top_srcdir)/common/m4/as-docbook.m4 \
$(top_srcdir)/common/m4/as-libtool.m4 \
- $(top_srcdir)/common/m4/as-scrub-include.m4 \
$(top_srcdir)/common/m4/as-version.m4 \
$(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/common/m4/gst-arch.m4 \
diff --git a/libs/gst/Makefile.in b/libs/gst/Makefile.in
index 5eaf2f1..6f9e86f 100644
--- a/libs/gst/Makefile.in
+++ b/libs/gst/Makefile.in
@@ -86,7 +86,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/as-compiler-flag.m4 \
$(top_srcdir)/common/m4/as-docbook.m4 \
$(top_srcdir)/common/m4/as-libtool.m4 \
- $(top_srcdir)/common/m4/as-scrub-include.m4 \
$(top_srcdir)/common/m4/as-version.m4 \
$(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/common/m4/gst-arch.m4 \
diff --git a/libs/gst/base/Makefile.am b/libs/gst/base/Makefile.am
index 076dc02..738e718 100644
--- a/libs/gst/base/Makefile.am
+++ b/libs/gst/base/Makefile.am
@@ -13,6 +13,7 @@ libgstbase_@GST_API_VERSION@_la_SOURCES = \
gstbytewriter.c \
gstcollectpads.c \
gstdataqueue.c \
+ gstflowcombiner.c \
gstpushsrc.c \
gstqueuearray.c \
gsttypefindhelper.c
@@ -36,6 +37,7 @@ libgstbase_@GST_API_VERSION@include_HEADERS = \
gstbytewriter.h \
gstcollectpads.h \
gstdataqueue.h \
+ gstflowcombiner.h \
gstpushsrc.h \
gstqueuearray.h \
gsttypefindhelper.h
@@ -89,7 +91,7 @@ GstBase-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstbase-@GST_API_VERS
--library-path=$(top_builddir)/gst \
--library=libgstbase-@GST_API_VERSION@.la \
--include=Gst-@GST_API_VERSION@ \
- --libtool="$(top_builddir)/libtool" \
+ --libtool="${LIBTOOL}" \
--pkg gstreamer-@GST_API_VERSION@ \
--pkg-export gstreamer-base-@GST_API_VERSION@ \
--add-init-section="gst_init(NULL,NULL);" \
diff --git a/libs/gst/base/Makefile.in b/libs/gst/base/Makefile.in
index 21884e8..601edaf 100644
--- a/libs/gst/base/Makefile.in
+++ b/libs/gst/base/Makefile.in
@@ -93,7 +93,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/as-compiler-flag.m4 \
$(top_srcdir)/common/m4/as-docbook.m4 \
$(top_srcdir)/common/m4/as-libtool.m4 \
- $(top_srcdir)/common/m4/as-scrub-include.m4 \
$(top_srcdir)/common/m4/as-version.m4 \
$(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/common/m4/gst-arch.m4 \
@@ -173,6 +172,7 @@ am_libgstbase_@GST_API_VERSION@_la_OBJECTS = \
libgstbase_@GST_API_VERSION@_la-gstbytewriter.lo \
libgstbase_@GST_API_VERSION@_la-gstcollectpads.lo \
libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo \
+ libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo \
libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo \
libgstbase_@GST_API_VERSION@_la-gstqueuearray.lo \
libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.lo
@@ -541,6 +541,7 @@ libgstbase_@GST_API_VERSION@_la_SOURCES = \
gstbytewriter.c \
gstcollectpads.c \
gstdataqueue.c \
+ gstflowcombiner.c \
gstpushsrc.c \
gstqueuearray.c \
gsttypefindhelper.c
@@ -563,6 +564,7 @@ libgstbase_@GST_API_VERSION@include_HEADERS = \
gstbytewriter.h \
gstcollectpads.h \
gstdataqueue.h \
+ gstflowcombiner.h \
gstpushsrc.h \
gstqueuearray.h \
gsttypefindhelper.h
@@ -674,6 +676,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstbytewriter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstcollectpads.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstdataqueue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstflowcombiner.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstqueuearray.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gsttypefindhelper.Plo@am__quote@
@@ -772,6 +775,13 @@ libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo: gstdataqueue.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstdataqueue.lo `test -f 'gstdataqueue.c' || echo '$(srcdir)/'`gstdataqueue.c
+libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo: gstflowcombiner.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstflowcombiner.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo `test -f 'gstflowcombiner.c' || echo '$(srcdir)/'`gstflowcombiner.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstflowcombiner.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstflowcombiner.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstflowcombiner.c' object='libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -c -o libgstbase_@GST_API_VERSION@_la-gstflowcombiner.lo `test -f 'gstflowcombiner.c' || echo '$(srcdir)/'`gstflowcombiner.c
+
libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo: gstpushsrc.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstbase_@GST_API_VERSION@_la_CFLAGS) $(CFLAGS) -MT libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo -MD -MP -MF $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Tpo -c -o libgstbase_@GST_API_VERSION@_la-gstpushsrc.lo `test -f 'gstpushsrc.c' || echo '$(srcdir)/'`gstpushsrc.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Tpo $(DEPDIR)/libgstbase_@GST_API_VERSION@_la-gstpushsrc.Plo
@@ -1112,7 +1122,7 @@ Android.mk: Makefile.am
@HAVE_INTROSPECTION_TRUE@ --library-path=$(top_builddir)/gst \
@HAVE_INTROSPECTION_TRUE@ --library=libgstbase-@GST_API_VERSION@.la \
@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \
-@HAVE_INTROSPECTION_TRUE@ --libtool="$(top_builddir)/libtool" \
+@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \
@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --pkg-export gstreamer-base-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --add-init-section="gst_init(NULL,NULL);" \
diff --git a/libs/gst/base/base.h b/libs/gst/base/base.h
index e741145..6646ce3 100644
--- a/libs/gst/base/base.h
+++ b/libs/gst/base/base.h
@@ -32,6 +32,7 @@
#include <gst/base/gstbytewriter.h>
#include <gst/base/gstcollectpads.h>
#include <gst/base/gstdataqueue.h>
+#include <gst/base/gstflowcombiner.h>
#include <gst/base/gstpushsrc.h>
#include <gst/base/gstqueuearray.h>
#include <gst/base/gsttypefindhelper.h>
diff --git a/libs/gst/base/gstadapter.c b/libs/gst/base/gstadapter.c
index 4c3e730..3d23fdb 100644
--- a/libs/gst/base/gstadapter.c
+++ b/libs/gst/base/gstadapter.c
@@ -70,13 +70,13 @@
* }
* ]|
*
- * For another example, a simple element inside GStreamer that uses GstAdapter
+ * For another example, a simple element inside GStreamer that uses #GstAdapter
* is the libvisual element.
*
- * An element using GstAdapter in its sink pad chain function should ensure that
+ * An element using #GstAdapter in its sink pad chain function should ensure that
* when the FLUSH_STOP event is received, that any queued data is cleared using
* gst_adapter_clear(). Data should also be cleared or processed on EOS and
- * when changing state from #GST_STATE_PAUSED to #GST_STATE_READY.
+ * when changing state from %GST_STATE_PAUSED to %GST_STATE_READY.
*
* Also check the GST_BUFFER_FLAG_DISCONT flag on the buffer. Some elements might
* need to clear the adapter after a discontinuity.
@@ -92,7 +92,7 @@
* gst_adapter_prev_pts_at_offset() can be used to determine the last
* seen timestamp at a particular offset in the adapter.
*
- * A last thing to note is that while GstAdapter is pretty optimized,
+ * A last thing to note is that while #GstAdapter is pretty optimized,
* merging buffers still might be an operation that requires a malloc() and
* memcpy() operation, and these operations are not the fastest. Because of
* this, some functions like gst_adapter_available_fast() are provided to help
@@ -100,17 +100,15 @@
* gst_adapter_copy() can be used to copy data into a (statically allocated)
* user provided buffer.
*
- * GstAdapter is not MT safe. All operations on an adapter must be serialized by
+ * #GstAdapter is not MT safe. All operations on an adapter must be serialized by
* the caller. This is not normally a problem, however, as the normal use case
- * of GstAdapter is inside one pad's chain function, in which case access is
+ * of #GstAdapter is inside one pad's chain function, in which case access is
* serialized via the pad's STREAM_LOCK.
*
* Note that gst_adapter_push() takes ownership of the buffer passed. Use
* gst_buffer_ref() before pushing it into the adapter if you still want to
* access the buffer later. The adapter will never modify the data in the
* buffer pushed in it.
- *
- * Last reviewed on 2009-05-13 (0.10.24).
*/
#include <gst/gst_private.h>
@@ -354,7 +352,7 @@ gst_adapter_push (GstAdapter * adapter, GstBuffer * buf)
/* Internal method only. Tries to merge buffers at the head of the queue
* to form a single larger buffer of size 'size'.
*
- * Returns TRUE if it managed to merge anything.
+ * Returns %TRUE if it managed to merge anything.
*/
static gboolean
gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size)
@@ -425,10 +423,10 @@ gst_adapter_try_to_merge_up (GstAdapter * adapter, gsize size)
* as #GstBuffer memory or the potentially more performant
* gst_adapter_take_buffer().
*
- * Returns #NULL if @size bytes are not available.
+ * Returns %NULL if @size bytes are not available.
*
* Returns: (transfer none) (array length=size) (element-type guint8):
- * a pointer to the first @size bytes of data, or NULL
+ * a pointer to the first @size bytes of data, or %NULL
*/
gconstpointer
gst_adapter_map (GstAdapter * adapter, gsize size)
@@ -526,7 +524,7 @@ gst_adapter_unmap (GstAdapter * adapter)
}
/**
- * gst_adapter_copy:
+ * gst_adapter_copy: (skip)
* @adapter: a #GstAdapter
* @dest: (out caller-allocates) (array length=size) (element-type guint8):
* the memory to copy into
@@ -534,7 +532,7 @@ gst_adapter_unmap (GstAdapter * adapter)
* @size: the number of bytes to copy
*
* Copies @size bytes of data starting at @offset out of the buffers
- * contained in @GstAdapter into an array @dest provided by the caller.
+ * contained in #GstAdapter into an array @dest provided by the caller.
*
* The array @dest should be large enough to contain @size bytes.
* The user should check that the adapter has (@offset + @size) bytes
@@ -550,6 +548,32 @@ gst_adapter_copy (GstAdapter * adapter, gpointer dest, gsize offset, gsize size)
copy_into_unchecked (adapter, dest, offset + adapter->skip, size);
}
+/**
+ * gst_adapter_copy_bytes:
+ * @adapter: a #GstAdapter
+ * @offset: the bytes offset in the adapter to start from
+ * @size: the number of bytes to copy
+ *
+ * Similar to gst_adapter_copy, but more suitable for language bindings. @size
+ * bytes of data starting at @offset will be copied out of the buffers contained
+ * in @adapter and into a new #GBytes structure which is returned. Depending on
+ * the value of the @size argument an empty #GBytes structure may be returned.
+ *
+ * Returns: (transfer full): A new #GBytes structure containing the copied data.
+ *
+ * Rename to: gst_adapter_copy
+ *
+ * Since: 1.4
+ */
+GBytes *
+gst_adapter_copy_bytes (GstAdapter * adapter, gsize offset, gsize size)
+{
+ gpointer data;
+ data = g_malloc (size);
+ gst_adapter_copy (adapter, data, offset, size);
+ return g_bytes_new_take (data, size);
+}
+
/*Flushes the first @flush bytes in the @adapter*/
static void
gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush)
@@ -685,7 +709,7 @@ gst_adapter_take_internal (GstAdapter * adapter, gsize nbytes)
* Free-function: g_free
*
* Returns: (transfer full) (array length=nbytes) (element-type guint8):
- * oven-fresh hot data, or #NULL if @nbytes bytes are not available
+ * oven-fresh hot data, or %NULL if @nbytes bytes are not available
*/
gpointer
gst_adapter_take (GstAdapter * adapter, gsize nbytes)
@@ -735,7 +759,7 @@ gst_adapter_take (GstAdapter * adapter, gsize nbytes)
* Free-function: gst_buffer_unref
*
* Returns: (transfer full): a #GstBuffer containing the first @nbytes of
- * the adapter, or #NULL if @nbytes bytes are not available.
+ * the adapter, or %NULL if @nbytes bytes are not available.
* gst_buffer_unref() when no longer needed.
*
* Since: 1.2
@@ -817,7 +841,7 @@ done:
* Free-function: gst_buffer_unref
*
* Returns: (transfer full): a #GstBuffer containing the first @nbytes of
- * the adapter, or #NULL if @nbytes bytes are not available.
+ * the adapter, or %NULL if @nbytes bytes are not available.
* gst_buffer_unref() when no longer needed.
*/
GstBuffer *
@@ -894,7 +918,7 @@ done:
* buffer in the list before freeing the list after usage.
*
* Returns: (element-type Gst.Buffer) (transfer full): a #GList of buffers
- * containing the first @nbytes of the adapter, or #NULL if @nbytes bytes
+ * containing the first @nbytes of the adapter, or %NULL if @nbytes bytes
* are not available
*/
GList *
@@ -929,7 +953,7 @@ gst_adapter_take_list (GstAdapter * adapter, gsize nbytes)
*
* Gets the maximum amount of bytes available, that is it returns the maximum
* value that can be supplied to gst_adapter_map() without that function
- * returning NULL.
+ * returning %NULL.
*
* Returns: number of bytes available in @adapter
*/
@@ -986,7 +1010,7 @@ gst_adapter_available_fast (GstAdapter * adapter)
/**
* gst_adapter_prev_pts:
* @adapter: a #GstAdapter
- * @distance: (out) (allow-none): pointer to location for distance, or NULL
+ * @distance: (out) (allow-none): pointer to location for distance, or %NULL
*
* Get the pts that was before the current byte in the adapter. When
* @distance is given, the amount of bytes between the pts and the current
@@ -1013,7 +1037,7 @@ gst_adapter_prev_pts (GstAdapter * adapter, guint64 * distance)
/**
* gst_adapter_prev_dts:
* @adapter: a #GstAdapter
- * @distance: (out) (allow-none): pointer to location for distance, or NULL
+ * @distance: (out) (allow-none): pointer to location for distance, or %NULL
*
* Get the dts that was before the current byte in the adapter. When
* @distance is given, the amount of bytes between the dts and the current
@@ -1041,7 +1065,7 @@ gst_adapter_prev_dts (GstAdapter * adapter, guint64 * distance)
* gst_adapter_prev_pts_at_offset:
* @adapter: a #GstAdapter
* @offset: the offset in the adapter at which to get timestamp
- * @distance: (out) (allow-none): pointer to location for distance, or NULL
+ * @distance: (out) (allow-none): pointer to location for distance, or %NULL
*
* Get the pts that was before the byte at offset @offset in the adapter. When
* @distance is given, the amount of bytes between the pts and the current
@@ -1065,7 +1089,6 @@ gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset,
GstClockTime pts = adapter->pts;
g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
- g_return_val_if_fail (offset >= 0, GST_CLOCK_TIME_NONE);
g = adapter->buflist;
@@ -1090,7 +1113,7 @@ gst_adapter_prev_pts_at_offset (GstAdapter * adapter, gsize offset,
* gst_adapter_prev_dts_at_offset:
* @adapter: a #GstAdapter
* @offset: the offset in the adapter at which to get timestamp
- * @distance: (out) (allow-none): pointer to location for distance, or NULL
+ * @distance: (out) (allow-none): pointer to location for distance, or %NULL
*
* Get the dts that was before the byte at offset @offset in the adapter. When
* @distance is given, the amount of bytes between the dts and the current
@@ -1114,7 +1137,6 @@ gst_adapter_prev_dts_at_offset (GstAdapter * adapter, gsize offset,
GstClockTime dts = adapter->dts;
g_return_val_if_fail (GST_IS_ADAPTER (adapter), GST_CLOCK_TIME_NONE);
- g_return_val_if_fail (offset >= 0, GST_CLOCK_TIME_NONE);
g = adapter->buflist;
@@ -1270,7 +1292,7 @@ gst_adapter_masked_scan_uint32_peek (GstAdapter * adapter, guint32 mask,
* It is an error to call this function without making sure that there is
* enough data (offset+size bytes) in the adapter.
*
- * This function calls gst_adapter_masked_scan_uint32_peek() passing NULL
+ * This function calls gst_adapter_masked_scan_uint32_peek() passing %NULL
* for value.
*
* Returns: offset of the first match, or -1 if no match was found.
diff --git a/libs/gst/base/gstadapter.h b/libs/gst/base/gstadapter.h
index 9683f3b..f82fbfb 100644
--- a/libs/gst/base/gstadapter.h
+++ b/libs/gst/base/gstadapter.h
@@ -56,6 +56,8 @@ gconstpointer gst_adapter_map (GstAdapter *adapter, gs
void gst_adapter_unmap (GstAdapter *adapter);
void gst_adapter_copy (GstAdapter *adapter, gpointer dest,
gsize offset, gsize size);
+GBytes * gst_adapter_copy_bytes (GstAdapter *adapter,
+ gsize offset, gsize size);
void gst_adapter_flush (GstAdapter *adapter, gsize flush);
gpointer gst_adapter_take (GstAdapter *adapter, gsize nbytes);
GstBuffer* gst_adapter_take_buffer (GstAdapter *adapter, gsize nbytes);
diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c
index ec01738..c3e63e1 100644
--- a/libs/gst/base/gstbaseparse.c
+++ b/libs/gst/base/gstbaseparse.c
@@ -50,22 +50,22 @@
* <listitem>
* <itemizedlist><title>Set-up phase</title>
* <listitem><para>
- * GstBaseParse calls @start to inform subclass that data processing is
+ * #GstBaseParse calls @start to inform subclass that data processing is
* about to start now.
* </para></listitem>
* <listitem><para>
- * GstBaseParse class calls @set_sink_caps to inform the subclass about
+ * #GstBaseParse class calls @set_sink_caps to inform the subclass about
* incoming sinkpad caps. Subclass could already set the srcpad caps
* accordingly, but this might be delayed until calling
* gst_base_parse_finish_frame() with a non-queued frame.
* </para></listitem>
* <listitem><para>
- * At least at this point subclass needs to tell the GstBaseParse class
+ * At least at this point subclass needs to tell the #GstBaseParse class
* how big data chunks it wants to receive (min_frame_size). It can do
* this with gst_base_parse_set_min_frame_size().
* </para></listitem>
* <listitem><para>
- * GstBaseParse class sets up appropriate data passing mode (pull/push)
+ * #GstBaseParse class sets up appropriate data passing mode (pull/push)
* and starts to process the data.
* </para></listitem>
* </itemizedlist>
@@ -74,7 +74,7 @@
* <itemizedlist>
* <title>Parsing phase</title>
* <listitem><para>
- * GstBaseParse gathers at least min_frame_size bytes of data either
+ * #GstBaseParse gathers at least min_frame_size bytes of data either
* by pulling it from upstream or collecting buffers in an internal
* #GstAdapter.
* </para></listitem>
@@ -101,7 +101,7 @@
* </para><para>
* Subclass is also responsible for setting the buffer metadata
* (e.g. buffer timestamp and duration, or keyframe if applicable).
- * (although the latter can also be done by GstBaseParse if it is
+ * (although the latter can also be done by #GstBaseParse if it is
* appropriately configured, see below). Frame is provided with
* timestamp derived from upstream (as much as generally possible),
* duration obtained from configuration (see below), and offset
@@ -118,7 +118,7 @@
* events, or to perform custom (segment) filtering.
* </para></listitem>
* <listitem><para>
- * During the parsing process GstBaseParseClass will handle both srcpad
+ * During the parsing process #GstBaseParseClass will handle both srcpad
* and sinkpad events. They will be passed to subclass if @event or
* @src_event callbacks have been provided.
* </para></listitem>
@@ -127,7 +127,7 @@
* <listitem>
* <itemizedlist><title>Shutdown phase</title>
* <listitem><para>
- * GstBaseParse class calls @stop to inform the subclass that data
+ * #GstBaseParse class calls @stop to inform the subclass that data
* parsing will be stopped.
* </para></listitem>
* </itemizedlist>
@@ -139,12 +139,12 @@
* needs to set the fixed caps on srcpad, when the format is ensured (e.g.
* when base class calls subclass' @set_sink_caps function).
*
- * This base class uses #GST_FORMAT_DEFAULT as a meaning of frames. So,
+ * This base class uses %GST_FORMAT_DEFAULT as a meaning of frames. So,
* subclass conversion routine needs to know that conversion from
- * #GST_FORMAT_TIME to #GST_FORMAT_DEFAULT must return the
+ * %GST_FORMAT_TIME to %GST_FORMAT_DEFAULT must return the
* frame number that can be found from the given byte position.
*
- * GstBaseParse uses subclasses conversion methods also for seeking (or
+ * #GstBaseParse uses subclasses conversion methods also for seeking (or
* otherwise uses its own default one, see also below).
*
* Subclass @start and @stop functions will be called to inform the beginning
@@ -180,11 +180,11 @@
* <listitem><para>
* In particular, if subclass is unable to determine a duration, but
* parsing (or specs) yields a frames per seconds rate, then this can be
- * provided to GstBaseParse to enable it to cater for
+ * provided to #GstBaseParse to enable it to cater for
* buffer time metadata (which will be taken from upstream as much as
* possible). Internally keeping track of frame durations and respective
- * sizes that have been pushed provides GstBaseParse with an estimated
- * bitrate. A default @convert (used if not overriden) will then use these
+ * sizes that have been pushed provides #GstBaseParse with an estimated
+ * bitrate. A default @convert (used if not overridden) will then use these
* rates to perform obvious conversions. These rates are also used to
* update (estimated) duration at regular frame intervals.
* </para></listitem>
@@ -561,11 +561,11 @@ gst_base_parse_class_init (GstBaseParseClass * klass)
/**
* GstBaseParse:disable-passthrough:
*
- * If set to #TRUE, baseparse will unconditionally force parsing of the
+ * If set to %TRUE, baseparse will unconditionally force parsing of the
* incoming data. This can be required in the rare cases where the incoming
* side-data (caps, pts, dts, ...) is not trusted by the user and wants to
* force validation and parsing of the incoming data.
- * If set to #FALSE, decision of whether to parse the data or not is up to
+ * If set to %FALSE, decision of whether to parse the data or not is up to
* the implementation (standard behaviour).
*/
g_object_class_install_property (gobject_class, PROP_DISABLE_PASSTHROUGH,
@@ -898,7 +898,7 @@ gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
*
* Converts using configured "convert" vmethod in #GstBaseParse class.
*
- * Returns: TRUE if conversion was successful.
+ * Returns: %TRUE if conversion was successful.
*/
static gboolean
gst_base_parse_convert (GstBaseParse * parse,
@@ -949,7 +949,7 @@ gst_base_parse_convert (GstBaseParse * parse,
*
* Handler for sink pad events.
*
- * Returns: TRUE if the event was handled.
+ * Returns: %TRUE if the event was handled.
*/
static gboolean
gst_base_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
@@ -1012,6 +1012,8 @@ gst_base_parse_sink_event_default (GstBaseParse * parse, GstEvent * event)
gst_event_parse_segment (event, &in_segment);
gst_segment_init (&out_segment, GST_FORMAT_TIME);
+ out_segment.rate = in_segment->rate;
+ out_segment.applied_rate = in_segment->applied_rate;
GST_DEBUG_OBJECT (parse, "segment %" GST_SEGMENT_FORMAT, in_segment);
@@ -1349,7 +1351,7 @@ gst_base_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
*
* Handler for source pad events.
*
- * Returns: TRUE if the event was handled.
+ * Returns: %TRUE if the event was handled.
*/
static gboolean
gst_base_parse_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
@@ -1386,7 +1388,7 @@ gst_base_parse_is_seekable (GstBaseParse * parse)
*
* Default srcpad event handler.
*
- * Returns: TRUE if the event was handled and can be dropped.
+ * Returns: %TRUE if the event was handled and can be dropped.
*/
static gboolean
gst_base_parse_src_event_default (GstBaseParse * parse, GstEvent * event)
@@ -1417,7 +1419,7 @@ gst_base_parse_src_event_default (GstBaseParse * parse, GstEvent * event)
*
* Default implementation of "convert" vmethod in #GstBaseParse class.
*
- * Returns: TRUE if conversion was successful.
+ * Returns: %TRUE if conversion was successful.
*/
gboolean
gst_base_parse_convert_default (GstBaseParse * parse,
@@ -2502,6 +2504,7 @@ gst_base_parse_send_buffers (GstBaseParse * parse)
GSList *send = NULL;
GstBuffer *buf;
GstFlowReturn ret = GST_FLOW_OK;
+ gboolean first = TRUE;
send = parse->priv->buffers_send;
@@ -2515,6 +2518,13 @@ gst_base_parse_send_buffers (GstBaseParse * parse)
GST_TIME_ARGS (GST_BUFFER_PTS (buf)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf));
+ /* Make sure the first buffer is always DISCONT. If we split
+ * GOPs inside the parser this is otherwise not guaranteed */
+ if (first) {
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
+ first = FALSE;
+ }
+
/* iterate output queue an push downstream */
ret = gst_pad_push (parse->srcpad, buf);
send = g_slist_delete_link (send, send);
@@ -2670,8 +2680,10 @@ gst_base_parse_finish_fragment (GstBaseParse * parse, gboolean prev_head)
parse->priv->buffers_queued);
}
- /* audio may have all marked as keyframe, so arrange to send here */
- if (!seen_delta)
+ /* audio may have all marked as keyframe, so arrange to send here. Also
+ * we might have ended the loop above on a keyframe, in which case we
+ * should */
+ if (!seen_delta || seen_key)
ret = gst_base_parse_send_buffers (parse);
/* any trailing unused no longer usable (ideally none) */
@@ -3591,13 +3603,13 @@ gst_base_parse_set_pts_interpolation (GstBaseParse * parse,
* By default, the base class might try to infer PTS from DTS and vice
* versa. While this is generally correct for audio data, it may not
* be otherwise. Sub-classes implementing such formats should disable
- * timestamp infering.
+ * timestamp inferring.
*/
void
gst_base_parse_set_infer_ts (GstBaseParse * parse, gboolean infer_ts)
{
parse->priv->infer_ts = infer_ts;
- GST_INFO_OBJECT (parse, "TS infering: %s", (infer_ts) ? "yes" : "no");
+ GST_INFO_OBJECT (parse, "TS inferring: %s", (infer_ts) ? "yes" : "no");
}
/**
@@ -4492,7 +4504,7 @@ gst_base_parse_change_state (GstElement * element, GstStateChange transition)
*
* This function should only be called from a @handle_frame implementation.
*
- * GstBaseParse creates initial timestamps for frames by using the last
+ * #GstBaseParse creates initial timestamps for frames by using the last
* timestamp seen in the stream before the frame starts. In certain
* cases, the correct timestamps will occur in the stream after the
* start of the frame, but before the start of the actual picture data.
@@ -4507,7 +4519,6 @@ gst_base_parse_set_ts_at_offset (GstBaseParse * parse, gsize offset)
GstClockTime pts, dts;
g_return_if_fail (GST_IS_BASE_PARSE (parse));
- g_return_if_fail (offset >= 0);
pts = gst_adapter_prev_pts_at_offset (parse->priv->adapter, offset, NULL);
dts = gst_adapter_prev_dts_at_offset (parse->priv->adapter, offset, NULL);
diff --git a/libs/gst/base/gstbaseparse.h b/libs/gst/base/gstbaseparse.h
index 7393770..f84d973 100644
--- a/libs/gst/base/gstbaseparse.h
+++ b/libs/gst/base/gstbaseparse.h
@@ -94,7 +94,7 @@ G_BEGIN_DECLS
* that regular segment clipping can still be performed (as opposed to
* any custom one having been done).
* @GST_BASE_PARSE_FRAME_FLAG_DROP: indicates to @finish_frame that the
- * the frame should be dropped (and might be handled internall by subclass)
+ * the frame should be dropped (and might be handled internally by subclass)
* @GST_BASE_PARSE_FRAME_FLAG_QUEUE: indicates to @finish_frame that the
* the frame should be queued for now and processed fully later
* when the first non-queued frame is finished
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index 9fcacd6..b6fc1fc 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -44,7 +44,7 @@
* GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
*
* // sinktemplate should be a #GstStaticPadTemplate with direction
- * // #GST_PAD_SINK and name "sink"
+ * // %GST_PAD_SINK and name "sink"
* gst_element_class_add_pad_template (gstelement_class,
* gst_static_pad_template_get (&amp;sinktemplate));
*
@@ -57,14 +57,14 @@
* ]|
*
* #GstBaseSink will handle the prerolling correctly. This means that it will
- * return #GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first
+ * return %GST_STATE_CHANGE_ASYNC from a state change to PAUSED until the first
* buffer arrives in this element. The base class will call the
* #GstBaseSinkClass.preroll() vmethod with this preroll buffer and will then
* commit the state change to the next asynchronously pending state.
*
* When the element is set to PLAYING, #GstBaseSink will synchronise on the
* clock using the times returned from #GstBaseSinkClass.get_times(). If this
- * function returns #GST_CLOCK_TIME_NONE for the start time, no synchronisation
+ * function returns %GST_CLOCK_TIME_NONE for the start time, no synchronisation
* will be done. Synchronisation can be disabled entirely by setting the object
* #GstBaseSink:sync property to %FALSE.
*
@@ -84,14 +84,14 @@
* element receives EOS in PAUSED, preroll completes, the event is queued and an
* EOS message is posted when going to PLAYING.
*
- * #GstBaseSink will internally use the #GST_EVENT_SEGMENT events to schedule
+ * #GstBaseSink will internally use the %GST_EVENT_SEGMENT events to schedule
* synchronisation and clipping of buffers. Buffers that fall completely outside
* of the current segment are dropped. Buffers that fall partially in the
* segment are rendered (and prerolled). Subclasses should do any subbuffer
* clipping themselves when needed.
*
* #GstBaseSink will by default report the current playback position in
- * #GST_FORMAT_TIME based on the current clock time and segment information.
+ * %GST_FORMAT_TIME based on the current clock time and segment information.
* If no clock has been set on the element, the query will be forwarded
* upstream.
*
@@ -105,7 +105,7 @@
* #GstBaseSinkClass.start() and #GstBaseSinkClass.stop() calls.
*
* The #GstBaseSinkClass.event() virtual method will be called when an event is
- * received by #GstBaseSink. Normally this method should only be overriden by
+ * received by #GstBaseSink. Normally this method should only be overridden by
* very specific elements (such as file sinks) which need to handle the
* newsegment event specially.
*
@@ -138,8 +138,6 @@
* The #GstBaseSink:async property can be used to instruct the sink to never
* perform an ASYNC state change. This feature is mostly usable when dealing
* with non-synchronized streams or sparse streams.
- *
- * Last reviewed on 2007-08-29 (0.10.15)
*/
#ifdef HAVE_CONFIG_H
@@ -279,7 +277,7 @@ struct _GstBaseSinkPrivate
#define UPDATE_RUNNING_AVG(avg,val) DO_RUNNING_AVG(avg,val,8)
/* the windows for these running averages are experimentally obtained.
- * possitive values get averaged more while negative values use a small
+ * positive values get averaged more while negative values use a small
* window so we can react faster to badness. */
#define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16)
#define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4)
@@ -444,8 +442,8 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
/**
* GstBaseSink:async:
*
- * If set to #TRUE, the basesink will perform asynchronous state changes.
- * When set to #FALSE, the sink will not signal the parent when it prerolls.
+ * If set to %TRUE, the basesink will perform asynchronous state changes.
+ * When set to %FALSE, the sink will not signal the parent when it prerolls.
* Use this option when dealing with sparse streams or when synchronisation is
* not required.
*/
@@ -468,9 +466,9 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
/**
* GstBaseSink:enable-last-sample:
*
- * Enable the last-sample property. If FALSE, basesink doesn't keep a
+ * Enable the last-sample property. If %FALSE, basesink doesn't keep a
* reference to the last buffer arrived and the last-sample property is always
- * set to NULL. This can be useful if you need buffers to be released as soon
+ * set to %NULL. This can be useful if you need buffers to be released as soon
* as possible, eg. if you're using a buffer pool.
*/
g_object_class_install_property (gobject_class, PROP_ENABLE_LAST_SAMPLE,
@@ -483,7 +481,7 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
*
* The last buffer that arrived in the sink and was used for preroll or for
* rendering. This property can be used to generate thumbnails. This property
- * can be NULL when the sink has not yet received a bufer.
+ * can be %NULL when the sink has not yet received a buffer.
*/
g_object_class_install_property (gobject_class, PROP_LAST_SAMPLE,
g_param_spec_boxed ("last-sample", "Last Sample",
@@ -529,7 +527,7 @@ gst_base_sink_class_init (GstBaseSinkClass * klass)
* Setting this property to a value bigger than 0 will make the sink delay
* rendering of the buffers when it would exceed to max-bitrate.
*
- * Since: 1.1.1
+ * Since: 1.2
*/
g_object_class_install_property (gobject_class, PROP_MAX_BITRATE,
g_param_spec_uint64 ("max-bitrate", "Max Bitrate",
@@ -690,8 +688,8 @@ gst_base_sink_finalize (GObject * object)
* @sync: the new sync value.
*
* Configures @sink to synchronize on the clock or not. When
- * @sync is FALSE, incoming samples will be played as fast as
- * possible. If @sync is TRUE, the timestamps of the incomming
+ * @sync is %FALSE, incoming samples will be played as fast as
+ * possible. If @sync is %TRUE, the timestamps of the incoming
* buffers will be used to schedule the exact render time of its
* contents.
*/
@@ -712,7 +710,7 @@ gst_base_sink_set_sync (GstBaseSink * sink, gboolean sync)
* Checks if @sink is currently configured to synchronize against the
* clock.
*
- * Returns: TRUE if the sink is configured to synchronize against the clock.
+ * Returns: %TRUE if the sink is configured to synchronize against the clock.
*/
gboolean
gst_base_sink_get_sync (GstBaseSink * sink)
@@ -795,7 +793,7 @@ gst_base_sink_set_qos_enabled (GstBaseSink * sink, gboolean enabled)
* Checks if @sink is currently configured to send Quality-of-Service events
* upstream.
*
- * Returns: TRUE if the sink is configured to perform Quality-of-Service.
+ * Returns: %TRUE if the sink is configured to perform Quality-of-Service.
*/
gboolean
gst_base_sink_is_qos_enabled (GstBaseSink * sink)
@@ -814,7 +812,7 @@ gst_base_sink_is_qos_enabled (GstBaseSink * sink)
* @sink: the sink
* @enabled: the new async value.
*
- * Configures @sink to perform all state changes asynchronusly. When async is
+ * Configures @sink to perform all state changes asynchronously. When async is
* disabled, the sink will immediately go to PAUSED instead of waiting for a
* preroll buffer. This feature is useful if the sink does not synchronize
* against the clock or when it is dealing with sparse streams.
@@ -837,7 +835,7 @@ gst_base_sink_set_async_enabled (GstBaseSink * sink, gboolean enabled)
* Checks if @sink is currently configured to perform asynchronous state
* changes to PAUSED.
*
- * Returns: TRUE if the sink is configured to perform asynchronous state
+ * Returns: %TRUE if the sink is configured to perform asynchronous state
* changes.
*/
gboolean
@@ -907,7 +905,7 @@ gst_base_sink_get_ts_offset (GstBaseSink * sink)
* Free-function: gst_sample_unref
*
* Returns: (transfer full): a #GstSample. gst_sample_unref() after usage.
- * This function returns NULL when no buffer has arrived in the sink yet
+ * This function returns %NULL when no buffer has arrived in the sink yet
* or when the sink is not in PAUSED or PLAYING.
*/
GstSample *
@@ -996,7 +994,7 @@ gst_base_sink_set_last_sample_enabled (GstBaseSink * sink, gboolean enabled)
* Checks if @sink is currently configured to store the last received sample in
* the last-sample property.
*
- * Returns: TRUE if the sink is configured to store the last received sample.
+ * Returns: %TRUE if the sink is configured to store the last received sample.
*/
gboolean
gst_base_sink_is_last_sample_enabled (GstBaseSink * sink)
@@ -1035,17 +1033,17 @@ gst_base_sink_get_latency (GstBaseSink * sink)
* @max_latency: (out) (allow-none): the max latency of the upstream elements
*
* Query the sink for the latency parameters. The latency will be queried from
- * the upstream elements. @live will be TRUE if @sink is configured to
- * synchronize against the clock. @upstream_live will be TRUE if an upstream
+ * the upstream elements. @live will be %TRUE if @sink is configured to
+ * synchronize against the clock. @upstream_live will be %TRUE if an upstream
* element is live.
*
- * If both @live and @upstream_live are TRUE, the sink will want to compensate
+ * If both @live and @upstream_live are %TRUE, the sink will want to compensate
* for the latency introduced by the upstream elements by setting the
- * @min_latency to a strictly possitive value.
+ * @min_latency to a strictly positive value.
*
* This function is mostly used by subclasses.
*
- * Returns: TRUE if the query succeeded.
+ * Returns: %TRUE if the query succeeded.
*/
gboolean
gst_base_sink_query_latency (GstBaseSink * sink, gboolean * live,
@@ -1280,7 +1278,7 @@ gst_base_sink_get_throttle_time (GstBaseSink * sink)
*
* Set the maximum amount of bits per second that the sink will render.
*
- * Since: 1.1.1
+ * Since: 1.2
*/
void
gst_base_sink_set_max_bitrate (GstBaseSink * sink, guint64 max_bitrate)
@@ -1301,7 +1299,7 @@ gst_base_sink_set_max_bitrate (GstBaseSink * sink, guint64 max_bitrate)
*
* Returns: the maximum number of bits per second @sink will render.
*
- * Since: 1.1.1
+ * Since: 1.2
*/
guint64
gst_base_sink_get_max_bitrate (GstBaseSink * sink)
@@ -1528,8 +1526,8 @@ nothing_pending:
/* Depending on the state, set our vars. We get in this situation when the
* state change function got a change to update the state vars before the
* streaming thread did. This is fine but we need to make sure that we
- * update the need_preroll var since it was TRUE when we got here and might
- * become FALSE if we got to PLAYING. */
+ * update the need_preroll var since it was %TRUE when we got here and might
+ * become %FALSE if we got to PLAYING. */
GST_DEBUG_OBJECT (basesink, "nothing to commit, now in %s",
gst_element_state_get_name (current));
switch (current) {
@@ -1789,7 +1787,7 @@ handle_stepping (GstBaseSink * sink, GstSegment * segment,
/* with STREAM_LOCK, PREROLL_LOCK
*
- * Returns TRUE if the object needs synchronisation and takes therefore
+ * Returns %TRUE if the object needs synchronisation and takes therefore
* part in prerolling.
*
* rsstart/rsstop contain the start/stop in stream time.
@@ -1981,7 +1979,7 @@ eos_done:
out_of_segment:
{
/* we usually clip in the chain function already but stepping could cause
- * the segment to be updated later. we return FALSE so that we don't try
+ * the segment to be updated later. we return %FALSE so that we don't try
* to sync on it. */
GST_LOG_OBJECT (basesink, "buffer skipped, not in segment");
return FALSE;
@@ -2002,7 +2000,7 @@ gst_base_sink_adjust_time (GstBaseSink * basesink, GstClockTime time)
time += basesink->priv->latency;
- /* apply offset, be carefull for underflows */
+ /* apply offset, be careful for underflows */
ts_offset = basesink->priv->ts_offset;
if (ts_offset < 0) {
ts_offset = -ts_offset;
@@ -2026,14 +2024,14 @@ gst_base_sink_adjust_time (GstBaseSink * basesink, GstClockTime time)
* gst_base_sink_wait_clock:
* @sink: the sink
* @time: the running_time to be reached
- * @jitter: (out) (allow-none): the jitter to be filled with time diff, or NULL
+ * @jitter: (out) (allow-none): the jitter to be filled with time diff, or %NULL
*
* This function will block until @time is reached. It is usually called by
* subclasses that use their own internal synchronisation.
*
- * If @time is not valid, no sycnhronisation is done and #GST_CLOCK_BADTIME is
+ * If @time is not valid, no synchronisation is done and %GST_CLOCK_BADTIME is
* returned. Likewise, if synchronisation is disabled in the element or there
- * is no clock, no synchronisation is done and #GST_CLOCK_BADTIME is returned.
+ * is no clock, no synchronisation is done and %GST_CLOCK_BADTIME is returned.
*
* This function should only be called with the PREROLL_LOCK held, like when
* receiving an EOS event in the #GstBaseSinkClass.event() vmethod or when
@@ -2076,8 +2074,8 @@ gst_base_sink_wait_clock (GstBaseSink * sink, GstClockTime time,
/* 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)) {
+ && 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);
@@ -2134,14 +2132,14 @@ no_clock:
* and call this method before continuing to render the remaining data.
*
* This function will block until a state change to PLAYING happens (in which
- * case this function returns #GST_FLOW_OK) or the processing must be stopped due
+ * case this function returns %GST_FLOW_OK) or the processing must be stopped due
* to a state change to READY or a FLUSH event (in which case this function
- * returns #GST_FLOW_FLUSHING).
+ * returns %GST_FLOW_FLUSHING).
*
* This function should only be called with the PREROLL_LOCK held, like in the
* render function.
*
- * Returns: #GST_FLOW_OK if the preroll completed and processing can
+ * Returns: %GST_FLOW_OK if the preroll completed and processing can
* continue. Any other return value should be returned from the render vmethod.
*/
GstFlowReturn
@@ -2186,7 +2184,7 @@ step_unlocked:
*
* This function should be called with the PREROLL_LOCK held.
*
- * Returns: #GST_FLOW_OK if the preroll completed and processing can
+ * Returns: %GST_FLOW_OK if the preroll completed and processing can
* continue. Any other return value should be returned from the render vmethod.
*/
GstFlowReturn
@@ -2276,7 +2274,7 @@ preroll_failed:
* gst_base_sink_wait:
* @sink: the sink
* @time: the running_time to be reached
- * @jitter: (out) (allow-none): the jitter to be filled with time diff, or NULL
+ * @jitter: (out) (allow-none): the jitter to be filled with time diff, or %NULL
*
* This function will wait for preroll to complete and will then block until @time
* is reached. It is usually called by subclasses that use their own internal
@@ -2362,7 +2360,7 @@ flushing:
* immediately returns GST_FLOW_OK.
*
* for objects that arrive later than max-lateness to be synchronized to the
- * clock have the @late boolean set to TRUE.
+ * clock have the @late boolean set to %TRUE.
*
* This function keeps a running average of the jitter (the diff between the
* clock time and the requested sync time). The jitter is negative for
@@ -2732,7 +2730,7 @@ gst_base_sink_reset_qos (GstBaseSink * sink)
*
* status and jitter contain the return values from the clock wait.
*
- * returns TRUE if the buffer was too late.
+ * returns %TRUE if the buffer was too late.
*/
static gboolean
gst_base_sink_is_too_late (GstBaseSink * basesink, GstMiniObject * obj,
@@ -2857,6 +2855,44 @@ gst_base_sink_do_render_stats (GstBaseSink * basesink, gboolean start)
}
static void
+gst_base_sink_update_start_time (GstBaseSink * basesink)
+{
+ GstClock *clock;
+
+ GST_OBJECT_LOCK (basesink);
+ if ((clock = GST_ELEMENT_CLOCK (basesink))) {
+ GstClockTime now;
+
+ gst_object_ref (clock);
+ GST_OBJECT_UNLOCK (basesink);
+
+ /* calculate the time when we stopped */
+ now = gst_clock_get_time (clock);
+ gst_object_unref (clock);
+
+ GST_OBJECT_LOCK (basesink);
+ /* store the current running time */
+ if (GST_ELEMENT_START_TIME (basesink) != GST_CLOCK_TIME_NONE) {
+ if (now != GST_CLOCK_TIME_NONE)
+ GST_ELEMENT_START_TIME (basesink) =
+ now - GST_ELEMENT_CAST (basesink)->base_time;
+ else
+ GST_WARNING_OBJECT (basesink,
+ "Clock %s returned invalid time, can't calculate "
+ "running_time when going to the PAUSED state",
+ GST_OBJECT_NAME (clock));
+ }
+ GST_DEBUG_OBJECT (basesink,
+ "start_time=%" GST_TIME_FORMAT ", now=%" GST_TIME_FORMAT
+ ", base_time %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (GST_ELEMENT_START_TIME (basesink)),
+ GST_TIME_ARGS (now),
+ GST_TIME_ARGS (GST_ELEMENT_CAST (basesink)->base_time));
+ }
+ GST_OBJECT_UNLOCK (basesink);
+}
+
+static void
gst_base_sink_flush_start (GstBaseSink * basesink, GstPad * pad)
{
/* make sure we are not blocked on the clock also clear any pending
@@ -2872,6 +2908,7 @@ gst_base_sink_flush_start (GstBaseSink * basesink, GstPad * pad)
* prerolled buffer */
basesink->playing_async = TRUE;
if (basesink->priv->async_enabled) {
+ gst_base_sink_update_start_time (basesink);
gst_element_lost_state (GST_ELEMENT_CAST (basesink));
} else {
/* start time reset in above case as well;
@@ -3236,7 +3273,7 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
GstSegment *segment;
GstBuffer *sync_buf;
gint do_qos;
- gboolean late, step_end;
+ gboolean late, step_end, prepared = FALSE;
if (G_UNLIKELY (basesink->flushing))
goto flushing;
@@ -3310,11 +3347,15 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
gst_base_sink_get_sync_times (basesink, obj, &sstart, &sstop, &rstart,
&rstop, &rnext, &do_sync, &stepped, current, &step_end);
- if (!stepped && syncable && do_sync)
+ if (G_UNLIKELY (stepped))
+ goto dropped;
+
+ if (syncable && do_sync)
late =
gst_base_sink_is_too_late (basesink, obj, rstart, rstop,
GST_CLOCK_EARLY, 0, FALSE);
- if (late)
+
+ if (G_UNLIKELY (late))
goto dropped;
if (!is_list) {
@@ -3330,6 +3371,8 @@ gst_base_sink_chain_unlocked (GstBaseSink * basesink, GstPad * pad,
goto prepare_failed;
}
}
+
+ prepared = TRUE;
}
again:
@@ -3343,6 +3386,9 @@ again:
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto sync_failed;
+ /* Don't skip if prepare() was called on time */
+ late = late && !prepared;
+
/* drop late buffers unconditionally, let's hope it's unlikely */
if (G_UNLIKELY (late))
goto dropped;
@@ -3819,6 +3865,7 @@ gst_base_sink_perform_step (GstBaseSink * sink, GstPad * pad, GstEvent * event)
sink->playing_async = TRUE;
priv->pending_step.need_preroll = TRUE;
sink->need_preroll = FALSE;
+ gst_base_sink_update_start_time (sink);
gst_element_lost_state (GST_ELEMENT_CAST (sink));
} else {
sink->priv->have_latency = TRUE;
@@ -4128,7 +4175,7 @@ gst_base_sink_negotiate_pull (GstBaseSink * basesink)
result = FALSE;
/* this returns the intersection between our caps and the peer caps. If there
- * is no peer, it returns NULL and we can't operate in pull mode so we can
+ * is no peer, it returns %NULL and we can't operate in pull mode so we can
* fail the negotiation. */
caps = gst_pad_get_allowed_caps (GST_BASE_SINK_PAD (basesink));
if (caps == NULL || gst_caps_is_empty (caps))
@@ -4431,9 +4478,8 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
start = basesink->priv->current_sstart;
stop = basesink->priv->current_sstop;
- if (in_paused || last_seen) {
- /* in paused or when we don't use the clock, we use the last position
- * as a lower bound */
+ if (last_seen) {
+ /* when we don't use the clock, we use the last position as a lower bound */
if (stop == -1 || segment->rate > 0.0)
last = start;
else
@@ -4442,7 +4488,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
GST_DEBUG_OBJECT (basesink, "in PAUSED using last %" GST_TIME_FORMAT,
GST_TIME_ARGS (last));
} else {
- /* in playing, use last stop time as upper bound */
+ /* in playing and paused, use last stop time as upper bound */
if (start == -1 || segment->rate > 0.0)
last = stop;
else
@@ -4519,15 +4565,9 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
*cur = time + gst_guint64_to_gdouble (now - base_time) * rate;
- if (in_paused) {
- /* never report less than segment values in paused */
- if (last != -1)
- *cur = MAX (last, *cur);
- } else {
- /* never report more than last seen position in playing */
- if (last != -1)
- *cur = MIN (last, *cur);
- }
+ /* never report more than last seen position */
+ if (last != -1)
+ *cur = MIN (last, *cur);
GST_DEBUG_OBJECT (basesink,
"now %" GST_TIME_FORMAT " - base_time %" GST_TIME_FORMAT " - base %"
@@ -4785,14 +4825,27 @@ gst_base_sink_default_query (GstBaseSink * basesink, GstQuery * query)
gst_query_parse_accept_caps (query, &caps);
allowed = gst_base_sink_query_caps (basesink, basesink->sinkpad, NULL);
subset = gst_caps_is_subset (caps, allowed);
+ GST_DEBUG_OBJECT (basesink, "Checking if requested caps %" GST_PTR_FORMAT
+ " are a subset of pad caps %" GST_PTR_FORMAT " result %d", caps,
+ allowed, subset);
gst_caps_unref (allowed);
gst_query_set_accept_caps_result (query, subset);
res = TRUE;
break;
}
case GST_QUERY_DRAIN:
+ {
+ GstBuffer *old;
+
+ GST_OBJECT_LOCK (basesink);
+ if ((old = basesink->priv->last_buffer))
+ basesink->priv->last_buffer = gst_buffer_copy (old);
+ GST_OBJECT_UNLOCK (basesink);
+ if (old)
+ gst_buffer_unref (old);
res = TRUE;
break;
+ }
default:
res =
gst_pad_query_default (basesink->sinkpad, GST_OBJECT_CAST (basesink),
diff --git a/libs/gst/base/gstbasesink.h b/libs/gst/base/gstbasesink.h
index 6f2ade7..d09b7e8 100644
--- a/libs/gst/base/gstbasesink.h
+++ b/libs/gst/base/gstbasesink.h
@@ -137,7 +137,7 @@ struct _GstBaseSink {
* @preroll: Called to present the preroll buffer if desired.
* @render: Called when a buffer should be presented or output, at the
* correct moment if the #GstBaseSink has been set to sync to the clock.
- * @render_list: Same as @render but used whith buffer lists instead of
+ * @render_list: Same as @render but used with buffer lists instead of
* buffers.
*
* Subclasses can override any of the available virtual methods or not, as
diff --git a/libs/gst/base/gstbasesrc.c b/libs/gst/base/gstbasesrc.c
index dd55e32..eb861a3 100644
--- a/libs/gst/base/gstbasesrc.c
+++ b/libs/gst/base/gstbasesrc.c
@@ -25,7 +25,7 @@
* @short_description: Base class for getrange based source elements
* @see_also: #GstPushSrc, #GstBaseTransform, #GstBaseSink
*
- * This is a generice base class for source elements. The following
+ * This is a generic base class for source elements. The following
* types of sources are supported:
* <itemizedlist>
* <listitem><para>random access sources like files</para></listitem>
@@ -35,13 +35,13 @@
*
* The source can be configured to operate in any #GstFormat with the
* gst_base_src_set_format() method. The currently set format determines
- * the format of the internal #GstSegment and any #GST_EVENT_SEGMENT
- * events. The default format for #GstBaseSrc is #GST_FORMAT_BYTES.
+ * the format of the internal #GstSegment and any %GST_EVENT_SEGMENT
+ * events. The default format for #GstBaseSrc is %GST_FORMAT_BYTES.
*
* #GstBaseSrc always supports push mode scheduling. If the following
* conditions are met, it also supports pull mode scheduling:
* <itemizedlist>
- * <listitem><para>The format is set to #GST_FORMAT_BYTES (default).</para>
+ * <listitem><para>The format is set to %GST_FORMAT_BYTES (default).</para>
* </listitem>
* <listitem><para>#GstBaseSrcClass.is_seekable() returns %TRUE.</para>
* </listitem>
@@ -50,7 +50,7 @@
* If all the conditions are met for operating in pull mode, #GstBaseSrc is
* automatically seekable in push mode as well. The following conditions must
* be met to make the element seekable in push mode when the format is not
- * #GST_FORMAT_BYTES:
+ * %GST_FORMAT_BYTES:
* <itemizedlist>
* <listitem><para>
* #GstBaseSrcClass.is_seekable() returns %TRUE.
@@ -82,7 +82,7 @@
* #GstBaseSrcClass.create() method will not be called in PAUSED but only in
* PLAYING. To signal the pipeline that the element will not produce data, the
* return value from the READY to PAUSED state will be
- * #GST_STATE_CHANGE_NO_PREROLL.
+ * %GST_STATE_CHANGE_NO_PREROLL.
*
* A typical live source will timestamp the buffers it creates with the
* current running time of the pipeline. This is one reason why a live source
@@ -118,7 +118,7 @@
* {
* GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
* // srctemplate should be a #GstStaticPadTemplate with direction
- * // #GST_PAD_SRC and name "src"
+ * // %GST_PAD_SRC and name "src"
* gst_element_class_add_pad_template (gstelement_class,
* gst_static_pad_template_get (&amp;srctemplate));
*
@@ -144,14 +144,12 @@
*
* An application may send an EOS event to a source element to make it
* perform the EOS logic (send EOS event downstream or post a
- * #GST_MESSAGE_SEGMENT_DONE on the bus). This can typically be done
+ * %GST_MESSAGE_SEGMENT_DONE on the bus). This can typically be done
* with the gst_element_send_event() function on the element or its parent bin.
*
* After the EOS has been sent to the element, the application should wait for
* an EOS message to be posted on the pipeline's bus. Once this EOS message is
* received, it may safely shut down the entire pipeline.
- *
- * Last reviewed on 2007-12-19 (0.10.16)
* </para>
* </refsect2>
*/
@@ -188,6 +186,12 @@ GST_DEBUG_CATEGORY_STATIC (gst_base_src_debug);
#define GST_ASYNC_WAIT(elem) g_cond_wait (GST_ASYNC_GET_COND (elem), GST_OBJECT_GET_LOCK (elem))
#define GST_ASYNC_SIGNAL(elem) g_cond_signal (GST_ASYNC_GET_COND (elem));
+#define CLEAR_PENDING_EOS(bsrc) \
+ G_STMT_START { \
+ g_atomic_int_set (&bsrc->priv->has_pending_eos, FALSE); \
+ gst_event_replace (&bsrc->priv->pending_eos, NULL); \
+ } G_STMT_END
+
/* BaseSrc signals and args */
enum
@@ -230,7 +234,11 @@ struct _GstBaseSrcPrivate
guint32 segment_seqnum;
/* if EOS is pending (atomic) */
- gint pending_eos;
+ GstEvent *pending_eos;
+ gint has_pending_eos;
+
+ /* if the eos was caused by a forced eos from the application */
+ gboolean forced_eos;
/* startup latency is the time it takes between going to PLAYING and producing
* the first BUFFER with running_time 0. This value is included in the latency
@@ -242,6 +250,7 @@ struct _GstBaseSrcPrivate
gboolean do_timestamp;
volatile gint dynamic_size;
+ volatile gint automatic_eos;
/* stream sequence number */
guint32 seqnum;
@@ -425,6 +434,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
g_cond_init (&basesrc->live_cond);
basesrc->num_buffers = DEFAULT_NUM_BUFFERS;
basesrc->num_buffers_left = -1;
+ basesrc->priv->automatic_eos = TRUE;
basesrc->can_activate_push = TRUE;
@@ -496,11 +506,11 @@ gst_base_src_finalize (GObject * object)
* and call this method before continuing to produce the remaining data.
*
* This function will block until a state change to PLAYING happens (in which
- * case this function returns #GST_FLOW_OK) or the processing must be stopped due
+ * case this function returns %GST_FLOW_OK) or the processing must be stopped due
* to a state change to READY or a FLUSH event (in which case this function
- * returns #GST_FLOW_FLUSHING).
+ * returns %GST_FLOW_FLUSHING).
*
- * Returns: #GST_FLOW_OK if @src is PLAYING and processing can
+ * Returns: %GST_FLOW_OK if @src is PLAYING and processing can
* continue. Any other return value should be returned from the create vmethod.
*/
GstFlowReturn
@@ -582,7 +592,7 @@ gst_base_src_is_live (GstBaseSrc * src)
* for sending SEGMENT events and for performing seeks.
*
* If a format of GST_FORMAT_BYTES is set, the element will be able to
- * operate in pull mode if the #GstBaseSrcClass.is_seekable() returns TRUE.
+ * operate in pull mode if the #GstBaseSrcClass.is_seekable() returns %TRUE.
*
* This function must only be called in states < %GST_STATE_PAUSED.
*/
@@ -615,6 +625,26 @@ gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic)
}
/**
+ * gst_base_src_set_automatic_eos:
+ * @src: base source instance
+ * @automatic_eos: automatic eos
+ *
+ * If @automatic_eos is %TRUE, basesrc will automatically go EOS if a buffer
+ * after the total size is returned. By default this is %TRUE but sources
+ * that can't return an authoritative size and only know that they're EOS
+ * when trying to read more should set this to %FALSE.
+ *
+ * Since: 1.4
+ */
+void
+gst_base_src_set_automatic_eos (GstBaseSrc * src, gboolean automatic_eos)
+{
+ g_return_if_fail (GST_IS_BASE_SRC (src));
+
+ g_atomic_int_set (&src->priv->automatic_eos, automatic_eos);
+}
+
+/**
* gst_base_src_set_async:
* @src: base source instance
* @async: new async mode
@@ -664,14 +694,14 @@ gst_base_src_is_async (GstBaseSrc * src)
* @min_latency: (out) (allow-none): the min latency of the source
* @max_latency: (out) (allow-none): the max latency of the source
*
- * Query the source for the latency parameters. @live will be TRUE when @src is
+ * Query the source for the latency parameters. @live will be %TRUE when @src is
* configured as a live source. @min_latency will be set to the difference
* between the running time and the timestamp of the first buffer.
* @max_latency is always the undefined value of -1.
*
* This function is mostly used by subclasses.
*
- * Returns: TRUE if the query succeeded.
+ * Returns: %TRUE if the query succeeded.
*/
gboolean
gst_base_src_query_latency (GstBaseSrc * src, gboolean * live,
@@ -763,6 +793,8 @@ gst_base_src_set_do_timestamp (GstBaseSrc * src, gboolean timestamp)
GST_OBJECT_LOCK (src);
src->priv->do_timestamp = timestamp;
+ if (timestamp && src->segment.format != GST_FORMAT_TIME)
+ gst_segment_init (&src->segment, GST_FORMAT_TIME);
GST_OBJECT_UNLOCK (src);
}
@@ -793,7 +825,7 @@ gst_base_src_get_do_timestamp (GstBaseSrc * src)
* @src: The source
* @start: The new start value for the segment
* @stop: Stop value for the new segment
- * @time: The new time value for the start of the new segent
+ * @time: The new time value for the start of the new segment
*
* Prepare a new seamless segment for emission downstream. This function must
* only be called by derived sub-classes, and only from the create() function,
@@ -1727,7 +1759,12 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
GST_LIVE_LOCK (src);
src->priv->flushing = TRUE;
/* clear pending EOS if any */
- g_atomic_int_set (&src->priv->pending_eos, FALSE);
+ if (g_atomic_int_get (&src->priv->has_pending_eos)) {
+ GST_OBJECT_LOCK (src);
+ CLEAR_PENDING_EOS (src);
+ src->priv->forced_eos = FALSE;
+ GST_OBJECT_UNLOCK (src);
+ }
if (bclass->unlock_stop)
bclass->unlock_stop (src);
if (src->clock_id)
@@ -1768,18 +1805,24 @@ gst_base_src_send_event (GstElement * element, GstEvent * event)
*
* We have two possibilities:
*
- * - Before we are to enter the _create function, we check the pending_eos
+ * - Before we are to enter the _create function, we check the has_pending_eos
* first and do EOS instead of entering it.
* - If we are in the _create function or we did not manage to set the
* flag fast enough and we are about to enter the _create function,
* we unlock it so that we exit with FLUSHING immediately. We then
* check the EOS flag and do the EOS logic.
*/
- g_atomic_int_set (&src->priv->pending_eos, TRUE);
- GST_DEBUG_OBJECT (src, "EOS marked, calling unlock");
+ GST_OBJECT_LOCK (src);
+ g_atomic_int_set (&src->priv->has_pending_eos, TRUE);
+ if (src->priv->pending_eos)
+ gst_event_unref (src->priv->pending_eos);
+ src->priv->pending_eos = event;
+ event = NULL;
+ GST_OBJECT_UNLOCK (src);
+ GST_DEBUG_OBJECT (src, "EOS marked, calling unlock");
- /* unlock the _create function so that we can check the pending_eos flag
+ /* unlock the _create function so that we can check the has_pending_eos flag
* and we can do EOS. This will eventually release the LIVE_LOCK again so
* that we can grab it and stop the unlock again. We don't take the stream
* lock so that this operation is guaranteed to never block. */
@@ -2185,7 +2228,11 @@ gst_base_src_do_sync (GstBaseSrc * basesrc, GstBuffer * buffer)
if (do_timestamp) {
dts = running_time;
} else {
- dts = 0;
+ if (GST_CLOCK_TIME_IS_VALID (basesrc->segment.start)) {
+ dts = basesrc->segment.start;
+ } else {
+ dts = 0;
+ }
}
GST_BUFFER_DTS (buffer) = dts;
@@ -2277,10 +2324,14 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length,
if (format != GST_FORMAT_BYTES)
return TRUE;
- /* the max amount of bytes to read is the total size or
- * up to the segment.stop if present. */
- if (stop != -1)
- maxsize = MIN (size, stop);
+ /* when not doing automatic EOS, just use the stop position. We don't use
+ * the size to check for EOS */
+ if (!g_atomic_int_get (&src->priv->automatic_eos))
+ maxsize = stop;
+ /* Otherwise, the max amount of bytes to read is the total
+ * size or up to the segment.stop if present. */
+ else if (stop != -1)
+ maxsize = size != -1 ? MIN (size, stop) : stop;
else
maxsize = size;
@@ -2317,8 +2368,8 @@ gst_base_src_update_length (GstBaseSrc * src, guint64 offset, guint * length,
}
}
- /* keep track of current duration.
- * segment is in bytes, we checked that above. */
+ /* keep track of current duration. segment is in bytes, we checked
+ * that above. */
GST_OBJECT_LOCK (src);
src->segment.duration = size;
GST_OBJECT_UNLOCK (src);
@@ -2379,9 +2430,11 @@ again:
}
/* don't enter the create function if a pending EOS event was set. For the
- * logic of the pending_eos, check the event function of this class. */
- if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos)))
+ * logic of the has_pending_eos, check the event function of this class. */
+ if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) {
+ src->priv->forced_eos = TRUE;
goto eos;
+ }
GST_DEBUG_OBJECT (src,
"calling create offset %" G_GUINT64_FORMAT " length %u, time %"
@@ -2394,11 +2447,12 @@ again:
/* The create function could be unlocked because we have a pending EOS. It's
* possible that we have a valid buffer from create that we need to
* discard when the create function returned _OK. */
- if (G_UNLIKELY (g_atomic_int_get (&src->priv->pending_eos))) {
+ if (G_UNLIKELY (g_atomic_int_get (&src->priv->has_pending_eos))) {
if (ret == GST_FLOW_OK) {
if (*buf == NULL)
gst_buffer_unref (res_buf);
}
+ src->priv->forced_eos = TRUE;
goto eos;
}
@@ -2628,10 +2682,12 @@ gst_base_src_loop (GstPad * pad)
if (gst_pad_check_reconfigure (pad)) {
if (!gst_base_src_negotiate (src)) {
gst_pad_mark_reconfigure (pad);
- if (GST_PAD_IS_FLUSHING (pad))
+ if (GST_PAD_IS_FLUSHING (pad)) {
+ GST_LIVE_LOCK (src);
goto flushing;
- else
+ } else {
goto negotiate_failed;
+ }
}
}
@@ -2786,7 +2842,9 @@ gst_base_src_loop (GstPad * pad)
goto pause;
}
- if (G_UNLIKELY (eos)) {
+ /* Segment pending means that a new segment was configured
+ * during this loop run */
+ if (G_UNLIKELY (eos && !src->priv->segment_pending)) {
GST_INFO_OBJECT (src, "pausing after end of segment");
ret = GST_FLOW_EOS;
goto pause;
@@ -2831,12 +2889,19 @@ pause:
GstFormat format;
gint64 position;
- /* perform EOS logic */
flag_segment = (src->segment.flags & GST_SEGMENT_FLAG_SEGMENT) != 0;
format = src->segment.format;
position = src->segment.position;
- if (flag_segment) {
+ /* perform EOS logic */
+ if (src->priv->forced_eos) {
+ g_assert (g_atomic_int_get (&src->priv->has_pending_eos));
+ GST_OBJECT_LOCK (src);
+ event = src->priv->pending_eos;
+ src->priv->pending_eos = NULL;
+ GST_OBJECT_UNLOCK (src);
+
+ } else if (flag_segment) {
GstMessage *message;
message = gst_message_new_segment_done (GST_OBJECT_CAST (src),
@@ -2845,12 +2910,15 @@ pause:
gst_element_post_message (GST_ELEMENT_CAST (src), message);
event = gst_event_new_segment_done (format, position);
gst_event_set_seqnum (event, src->priv->seqnum);
- gst_pad_push_event (pad, event);
+
} else {
event = gst_event_new_eos ();
gst_event_set_seqnum (event, src->priv->seqnum);
- gst_pad_push_event (pad, event);
}
+
+ gst_pad_push_event (pad, event);
+ src->priv->forced_eos = FALSE;
+
} else if (ret == GST_FLOW_NOT_LINKED || ret <= GST_FLOW_EOS) {
event = gst_event_new_eos ();
gst_event_set_seqnum (event, src->priv->seqnum);
@@ -2987,7 +3055,25 @@ gst_base_src_decide_allocation_default (GstBaseSrc * basesrc, GstQuery * query)
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
gst_buffer_pool_config_set_allocator (config, allocator, &params);
- gst_buffer_pool_set_config (pool, config);
+
+ /* buffer pool may have to do some changes */
+ if (!gst_buffer_pool_set_config (pool, config)) {
+ config = gst_buffer_pool_get_config (pool);
+
+ /* If change are not acceptable, fallback to generic pool */
+ if (!gst_buffer_pool_config_validate_params (config, outcaps, size, min,
+ max)) {
+ GST_DEBUG_OBJECT (basesrc, "unsuported pool, making new pool");
+
+ gst_object_unref (pool);
+ pool = gst_buffer_pool_new ();
+ gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
+ gst_buffer_pool_config_set_allocator (config, allocator, &params);
+ }
+
+ if (!gst_buffer_pool_set_config (pool, config))
+ goto config_failed;
+ }
}
if (update_allocator)
@@ -3003,6 +3089,12 @@ gst_base_src_decide_allocation_default (GstBaseSrc * basesrc, GstQuery * query)
}
return TRUE;
+
+config_failed:
+ GST_ELEMENT_ERROR (basesrc, RESOURCE, SETTINGS,
+ ("Failed to configure the buffer pool"),
+ ("Configuration is most likely invalid, please report this issue."));
+ return FALSE;
}
static gboolean
@@ -3191,6 +3283,7 @@ gst_base_src_start (GstBaseSrc * basesrc)
basesrc->running = FALSE;
basesrc->priv->segment_pending = FALSE;
basesrc->priv->segment_seqnum = gst_util_seqnum_next ();
+ basesrc->priv->forced_eos = FALSE;
GST_LIVE_UNLOCK (basesrc);
bclass = GST_BASE_SRC_GET_CLASS (basesrc);
@@ -3305,24 +3398,30 @@ gst_base_src_start_complete (GstBaseSrc * basesrc, GstFlowReturn ret)
/* take the stream lock here, we only want to let the task run when we have
* set the STARTED flag */
GST_PAD_STREAM_LOCK (basesrc->srcpad);
- if (mode == GST_PAD_MODE_PUSH) {
- /* do initial seek, which will start the task */
- GST_OBJECT_LOCK (basesrc);
- event = basesrc->pending_seek;
- basesrc->pending_seek = NULL;
- GST_OBJECT_UNLOCK (basesrc);
-
- /* The perform seek code will start the task when finished. We don't have to
- * unlock the streaming thread because it is not running yet */
- if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE)))
- goto seek_failed;
-
- if (event)
- gst_event_unref (event);
- } else {
- /* if not random_access, we cannot operate in pull mode for now */
- if (G_UNLIKELY (!basesrc->random_access))
- goto no_get_range;
+ switch (mode) {
+ case GST_PAD_MODE_PUSH:
+ /* do initial seek, which will start the task */
+ GST_OBJECT_LOCK (basesrc);
+ event = basesrc->pending_seek;
+ basesrc->pending_seek = NULL;
+ GST_OBJECT_UNLOCK (basesrc);
+
+ /* The perform seek code will start the task when finished. We don't have to
+ * unlock the streaming thread because it is not running yet */
+ if (G_UNLIKELY (!gst_base_src_perform_seek (basesrc, event, FALSE)))
+ goto seek_failed;
+
+ if (event)
+ gst_event_unref (event);
+ break;
+ case GST_PAD_MODE_PULL:
+ /* if not random_access, we cannot operate in pull mode for now */
+ if (G_UNLIKELY (!basesrc->random_access))
+ goto no_get_range;
+ break;
+ default:
+ goto not_activated_yet;
+ break;
}
GST_OBJECT_LOCK (basesrc);
@@ -3354,6 +3453,14 @@ no_get_range:
ret = GST_FLOW_ERROR;
goto error;
}
+not_activated_yet:
+ {
+ GST_PAD_STREAM_UNLOCK (basesrc->srcpad);
+ gst_base_src_stop (basesrc);
+ GST_WARNING_OBJECT (basesrc, "pad not activated yet");
+ ret = GST_FLOW_ERROR;
+ goto error;
+ }
error:
{
GST_OBJECT_LOCK (basesrc);
@@ -3461,7 +3568,12 @@ gst_base_src_set_flushing (GstBaseSrc * basesrc,
basesrc->live_running = TRUE;
/* clear pending EOS if any */
- g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
+ if (g_atomic_int_get (&basesrc->priv->has_pending_eos)) {
+ GST_OBJECT_LOCK (basesrc);
+ CLEAR_PENDING_EOS (basesrc);
+ basesrc->priv->forced_eos = FALSE;
+ GST_OBJECT_UNLOCK (basesrc);
+ }
/* step 1, now that we have the LIVE lock, clear our unlock request */
if (bclass->unlock_stop)
@@ -3632,6 +3744,8 @@ gst_base_src_activate_mode (GstPad * pad, GstObject * parent,
src->priv->stream_start_pending = FALSE;
+ GST_DEBUG_OBJECT (pad, "activating in mode %d", mode);
+
switch (mode) {
case GST_PAD_MODE_PULL:
res = gst_base_src_activate_pull (pad, parent, active);
@@ -3693,7 +3807,11 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
{
/* we don't need to unblock anything here, the pad deactivation code
* already did this */
- g_atomic_int_set (&basesrc->priv->pending_eos, FALSE);
+ if (g_atomic_int_get (&basesrc->priv->has_pending_eos)) {
+ GST_OBJECT_LOCK (basesrc);
+ CLEAR_PENDING_EOS (basesrc);
+ GST_OBJECT_UNLOCK (basesrc);
+ }
gst_event_replace (&basesrc->pending_seek, NULL);
break;
}
@@ -3740,7 +3858,7 @@ gst_base_src_get_buffer_pool (GstBaseSrc * src)
* @allocator: (out) (allow-none) (transfer full): the #GstAllocator
* used
* @params: (out) (allow-none) (transfer full): the
- * #GstAllocatorParams of @allocator
+ * #GstAllocationParams of @allocator
*
* Lets #GstBaseSrc sub-classes to know the memory @allocator
* used by the base class and its @params.
diff --git a/libs/gst/base/gstbasesrc.h b/libs/gst/base/gstbasesrc.h
index 9afd5e0..75de438 100644
--- a/libs/gst/base/gstbasesrc.h
+++ b/libs/gst/base/gstbasesrc.h
@@ -129,28 +129,31 @@ struct _GstBaseSrc {
* these times.
* @get_size: Return the total size of the resource, in the configured format.
* @is_seekable: Check if the source can seek
- * @prepare_seek_segment: Prepare the GstSegment that will be passed to the
- * do_seek vmethod for executing a seek request. Sub-classes should override
- * this if they support seeking in formats other than the configured native
- * format. By default, it tries to convert the seek arguments to the
- * configured native format and prepare a segment in that format.
+ * @prepare_seek_segment: Prepare the #GstSegment that will be passed to the
+ * #GstBaseSrcClass.do_seek() vmethod for executing a seek
+ * request. Sub-classes should override this if they support seeking in
+ * formats other than the configured native format. By default, it tries to
+ * convert the seek arguments to the configured native format and prepare a
+ * segment in that format.
* @do_seek: Perform seeking on the resource to the indicated segment.
- * @unlock: Unlock any pending access to the resource. Subclasses should
- * unblock any blocked function ASAP. In particular, any create() function in
+ * @unlock: Unlock any pending access to the resource. Subclasses should unblock
+ * any blocked function ASAP. In particular, any create() function in
* progress should be unblocked and should return GST_FLOW_FLUSHING. Any
- * future @create<!-- -->() function call should also return GST_FLOW_FLUSHING
- * until the @unlock_stop<!-- -->() function has been called.
- * @unlock_stop: Clear the previous unlock request. Subclasses should clear
- * any state they set during unlock(), such as clearing command queues.
+ * future #GstBaseSrcClass.create() function call should also return
+ * GST_FLOW_FLUSHING until the #GstBaseSrcClass.unlock_stop() function has
+ * been called.
+ * @unlock_stop: Clear the previous unlock request. Subclasses should clear any
+ * state they set during #GstBaseSrcClass.unlock(), such as clearing command
+ * queues.
* @query: Handle a requested query.
* @event: Override this to implement custom event handling.
- * @create: Ask the subclass to create a buffer with offset and size.
- * When the subclass returns GST_FLOW_OK, it MUST return a buffer of the
- * requested size unless fewer bytes are available because an EOS condition
- * is near. No buffer should be returned when the return value is different
- * from GST_FLOW_OK. A return value of GST_FLOW_EOS signifies that the
- * end of stream is reached. The default implementation will call @alloc and
- * then call @fill.
+ * @create: Ask the subclass to create a buffer with offset and size. When the
+ * subclass returns GST_FLOW_OK, it MUST return a buffer of the requested size
+ * unless fewer bytes are available because an EOS condition is near. No
+ * buffer should be returned when the return value is different from
+ * GST_FLOW_OK. A return value of GST_FLOW_EOS signifies that the end of
+ * stream is reached. The default implementation will call
+ * #GstBaseSrcClass.alloc() and then call #GstBaseSrcClass.fill().
* @alloc: Ask the subclass to allocate a buffer with for offset and size. The
* default implementation will create a new buffer from the negotiated allocator.
* @fill: Ask the subclass to fill the buffer with data for offset and size. The
@@ -239,6 +242,8 @@ void gst_base_src_set_format (GstBaseSrc *src, GstFormat format
void gst_base_src_set_dynamic_size (GstBaseSrc * src, gboolean dynamic);
+void gst_base_src_set_automatic_eos (GstBaseSrc * src, gboolean automatic_eos);
+
void gst_base_src_set_async (GstBaseSrc *src, gboolean async);
gboolean gst_base_src_is_async (GstBaseSrc *src);
diff --git a/libs/gst/base/gstbasetransform.c b/libs/gst/base/gstbasetransform.c
index 8e28154..c20a613 100644
--- a/libs/gst/base/gstbasetransform.c
+++ b/libs/gst/base/gstbasetransform.c
@@ -57,14 +57,14 @@
* intact.
* </para></listitem>
* <listitem><para>
- * On the GstBaseTransformClass is the passthrough_on_same_caps variable
- * which will automatically set/unset passthrough based on whether the
+ * The #GstBaseTransformClass.passthrough_on_same_caps variable
+ * will automatically set/unset passthrough based on whether the
* element negotiates the same caps on both pads.
* </para></listitem>
* <listitem><para>
- * passthrough_on_same_caps on an element that doesn't implement a
- * transform_caps function is useful for elements that only inspect data
- * (such as level)
+ * #GstBaseTransformClass.passthrough_on_same_caps on an element that
+ * doesn't implement a transform_caps function is useful for elements that
+ * only inspect data (such as level)
* </para></listitem>
* </itemizedlist>
* <itemizedlist>
@@ -94,7 +94,7 @@
* immediately. </para></listitem>
* <listitem><para>
* only implementing transform_ip and not transform implies always_in_place
- * = TRUE
+ * = %TRUE
* </para></listitem>
* </itemizedlist>
* <itemizedlist>
@@ -116,7 +116,7 @@
* <listitem><para>
* Elements wishing to operate in this mode should replace the
* prepare_output_buffer method to create subbuffers of the input buffer
- * and set always_in_place to TRUE
+ * and set always_in_place to %TRUE
* </para></listitem>
* </itemizedlist>
* <itemizedlist>
@@ -185,10 +185,10 @@
* to the transform_ip function.
* </para></listitem>
* <listitem><para>
- * Implied TRUE if no transform function is implemented.
+ * Implied %TRUE if no transform function is implemented.
* </para></listitem>
* <listitem><para>
- * Implied FALSE if ONLY transform function is implemented.
+ * Implied %FALSE if ONLY transform function is implemented.
* </para></listitem>
* </itemizedlist>
* </para></listitem>
@@ -844,7 +844,7 @@ gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
/* by default we remove all metadata, subclasses should implement a
* filter_meta function */
- if (gst_meta_api_type_has_tag (api, GST_META_TAG_MEMORY)) {
+ if (gst_meta_api_type_has_tag (api, _gst_meta_tag_memory)) {
/* remove all memory dependent metadata because we are going to have to
* allocate different memory for input and output. */
GST_LOG_OBJECT (trans, "removing memory specific metadata %s",
@@ -899,7 +899,25 @@ gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
config = gst_buffer_pool_get_config (pool);
gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
gst_buffer_pool_config_set_allocator (config, allocator, &params);
- gst_buffer_pool_set_config (pool, config);
+
+ /* buffer pool may have to do some changes */
+ if (!gst_buffer_pool_set_config (pool, config)) {
+ config = gst_buffer_pool_get_config (pool);
+
+ /* If change are not acceptable, fallback to generic pool */
+ if (!gst_buffer_pool_config_validate_params (config, outcaps, size, min,
+ max)) {
+ GST_DEBUG_OBJECT (trans, "unsuported pool, making new pool");
+
+ gst_object_unref (pool);
+ pool = gst_buffer_pool_new ();
+ gst_buffer_pool_config_set_params (config, outcaps, size, min, max);
+ gst_buffer_pool_config_set_allocator (config, allocator, &params);
+ }
+
+ if (!gst_buffer_pool_set_config (pool, config))
+ goto config_failed;
+ }
}
if (update_allocator)
@@ -915,6 +933,12 @@ gst_base_transform_default_decide_allocation (GstBaseTransform * trans,
}
return TRUE;
+
+config_failed:
+ GST_ELEMENT_ERROR (trans, RESOURCE, SETTINGS,
+ ("Failed to configure the buffer pool"),
+ ("Configuration is most likely invalid, please report this issue."));
+ return FALSE;
}
static gboolean
@@ -1433,16 +1457,15 @@ gst_base_transform_default_query (GstBaseTransform * trans,
case GST_QUERY_ALLOCATION:
{
GstQuery *decide_query = NULL;
- gboolean negotiated;
/* can only be done on the sinkpad */
if (direction != GST_PAD_SINK)
goto done;
GST_OBJECT_LOCK (trans);
- if (G_UNLIKELY (!(negotiated = priv->negotiated))) {
+ if (!priv->negotiated && !priv->passthrough && (klass->set_caps != NULL)) {
GST_DEBUG_OBJECT (trans,
- "not negotiated yet, can't answer ALLOCATION query");
+ "not negotiated yet but need negotiation, can't answer ALLOCATION query");
GST_OBJECT_UNLOCK (trans);
goto done;
}
@@ -1558,7 +1581,7 @@ default_prepare_output_buffer (GstBaseTransform * trans,
/* figure out how to allocate an output buffer */
if (priv->passthrough) {
- /* passthrough, we will not modify the incomming buffer so we can just
+ /* passthrough, we will not modify the incoming buffer so we can just
* reuse it */
GST_DEBUG_OBJECT (trans, "passthrough: reusing input buffer");
*outbuf = inbuf;
@@ -1682,7 +1705,7 @@ foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
GST_DEBUG_OBJECT (trans, "not copying pooled metadata %s",
g_type_name (info->api));
do_copy = FALSE;
- } else if (gst_meta_api_type_has_tag (info->api, GST_META_TAG_MEMORY)) {
+ } else if (gst_meta_api_type_has_tag (info->api, _gst_meta_tag_memory)) {
/* never call the transform_meta with memory specific metadata */
GST_DEBUG_OBJECT (trans, "not copying memory specific metadata %s",
g_type_name (info->api));
@@ -1694,7 +1717,7 @@ foreach_metadata (GstBuffer * inbuf, GstMeta ** meta, gpointer user_data)
}
/* we only copy metadata when the subclass implemented a transform_meta
- * function and when it returns TRUE */
+ * function and when it returns %TRUE */
if (do_copy) {
GstMetaTransformCopy copy_data = { FALSE, 0, -1 };
GST_DEBUG_OBJECT (trans, "copy metadata %s", g_type_name (info->api));
@@ -1755,7 +1778,7 @@ not_writable:
* We have two cache locations to store the size, one for the source caps
* and one for the sink caps.
*
- * this function returns FALSE if no size could be calculated.
+ * this function returns %FALSE if no size could be calculated.
*/
static gboolean
gst_base_transform_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
@@ -2416,7 +2439,7 @@ gst_base_transform_src_activate_mode (GstPad * pad, GstObject * parent,
* Set passthrough mode for this filter by default. This is mostly
* useful for filters that do not care about negotiation.
*
- * Always TRUE for filters which don't implement either a transform
+ * Always %TRUE for filters which don't implement either a transform
* or transform_ip method.
*
* MT safe.
@@ -2449,7 +2472,7 @@ gst_base_transform_set_passthrough (GstBaseTransform * trans,
*
* See if @trans is configured as a passthrough transform.
*
- * Returns: TRUE is the transform is configured in passthrough mode.
+ * Returns: %TRUE is the transform is configured in passthrough mode.
*
* MT safe.
*/
@@ -2476,8 +2499,8 @@ gst_base_transform_is_passthrough (GstBaseTransform * trans)
* Determines whether a non-writable buffer will be copied before passing
* to the transform_ip function.
* <itemizedlist>
- * <listitem>Always TRUE if no transform function is implemented.</listitem>
- * <listitem>Always FALSE if ONLY transform function is implemented.</listitem>
+ * <listitem>Always %TRUE if no transform function is implemented.</listitem>
+ * <listitem>Always %FALSE if ONLY transform function is implemented.</listitem>
* </itemizedlist>
*
* MT safe.
@@ -2514,7 +2537,7 @@ gst_base_transform_set_in_place (GstBaseTransform * trans, gboolean in_place)
*
* See if @trans is configured as a in_place transform.
*
- * Returns: TRUE is the transform is configured in in_place mode.
+ * Returns: %TRUE is the transform is configured in in_place mode.
*
* MT safe.
*/
@@ -2589,7 +2612,7 @@ gst_base_transform_set_qos_enabled (GstBaseTransform * trans, gboolean enabled)
*
* Queries if the transform will handle QoS.
*
- * Returns: TRUE if QoS is enabled.
+ * Returns: %TRUE if QoS is enabled.
*
* MT safe.
*/
@@ -2642,7 +2665,7 @@ gst_base_transform_set_gap_aware (GstBaseTransform * trans, gboolean gap_aware)
* transform_caps vmethod.
*
* If set to %FALSE, the element must order the caps returned from the
- * transform_caps function in such a way that the prefered format is
+ * transform_caps function in such a way that the preferred format is
* first in the list. This can be interesting for transforms that can do
* passthrough transforms but prefer to do something else, like a
* capsfilter.
@@ -2722,7 +2745,7 @@ gst_base_transform_get_buffer_pool (GstBaseTransform * trans)
* @allocator: (out) (allow-none) (transfer full): the #GstAllocator
* used
* @params: (out) (allow-none) (transfer full): the
- * #GstAllocatorParams of @allocator
+ * #GstAllocationParams of @allocator
*
* Lets #GstBaseTransform sub-classes to know the memory @allocator
* used by the base class and its @params.
diff --git a/libs/gst/base/gstbasetransform.h b/libs/gst/base/gstbasetransform.h
index 3330503..3043a62 100644
--- a/libs/gst/base/gstbasetransform.h
+++ b/libs/gst/base/gstbasetransform.h
@@ -129,16 +129,16 @@ struct _GstBaseTransform {
* downstream allocation query. This function is only called
* when not operating in passthrough mode. The default
* implementation will remove all memory dependent metadata.
- * If there is ia @filter_meta method implementation, it will
+ * If there is a @filter_meta method implementation, it will
* be called for all metadata API in the downstream query,
* otherwise the metadata API is removed.
- * @filter_meta: Return TRUE if the metadata API should be proposed in the
- * upstream allocation query. The default implementation is NULL
+ * @filter_meta: Return %TRUE if the metadata API should be proposed in the
+ * upstream allocation query. The default implementation is %NULL
* and will cause all metadata to be removed.
* @propose_allocation: Propose buffer allocation parameters for upstream elements.
* This function must be implemented if the element reads or
* writes the buffer content. The query that was passed to
- * the decide_allocation is passed in this method (or NULL
+ * the decide_allocation is passed in this method (or %NULL
* when the element is in passthrough mode). The default
* implementation will pass the query downstream when in
* passthrough mode and will copy all the filtered metadata
@@ -176,9 +176,9 @@ struct _GstBaseTransform {
* The default implementation will copy the flags, timestamps and
* offsets of the buffer.
* @transform_meta: Optional. Transform the metadata on the input buffer to the
- * output buffer. By default this method is NULL and no
+ * output buffer. By default this method is %NULL and no
* metadata is copied. subclasses can implement this method and
- * return TRUE if the metadata is to be copied.
+ * return %TRUE if the metadata is to be copied.
* @before_transform: Optional.
* This method is called right before the base class will
* start processing. Dynamic properties or other delayed
diff --git a/libs/gst/base/gstbytereader.c b/libs/gst/base/gstbytereader.c
index a5f9e40..b73a679 100644
--- a/libs/gst/base/gstbytereader.c
+++ b/libs/gst/base/gstbytereader.c
@@ -775,23 +775,21 @@ gst_byte_reader_dup_data (GstByteReader * reader, guint size, guint8 ** val)
static inline gint
_scan_for_start_code (const guint8 * data, guint offset, guint size)
{
- guint i = 0;
-
- while (i <= (size - 4)) {
- if (data[i + 2] > 1) {
- i += 3;
- } else if (data[i + 1]) {
- i += 2;
- } else if (data[i] || data[i + 2] != 1) {
- i++;
+ guint8 *pdata = (guint8 *) data;
+ guint8 *pend = (guint8 *) (data + size - 4);
+
+ while (pdata <= pend) {
+ if (pdata[2] > 1) {
+ pdata += 3;
+ } else if (pdata[1]) {
+ pdata += 2;
+ } else if (pdata[0] || pdata[2] != 1) {
+ pdata++;
} else {
- break;
+ return (pdata - data + offset);
}
}
- if (i <= (size - 4))
- return i + offset;
-
/* nothing found */
return -1;
}
@@ -986,7 +984,7 @@ GST_BYTE_READER_SKIP_STRING (32);
* gst_byte_reader_peek_string:
* @reader: a #GstByteReader instance
* @str: (out) (transfer none) (array zero-terminated=1): address of a
- * #gchar pointer varieble in which to store the result
+ * #gchar pointer variable in which to store the result
*
* Returns a constant pointer to the current data position if there is
* a NUL-terminated string in the data (this could be just a NUL terminator).
@@ -1002,7 +1000,7 @@ GST_BYTE_READER_SKIP_STRING (32);
* gst_byte_reader_peek_string_utf8:
* @reader: a #GstByteReader instance
* @str: (out) (transfer none) (array zero-terminated=1): address of a
- * #gchar pointer varieble in which to store the result
+ * #gchar pointer variable in which to store the result
*
* Returns a constant pointer to the current data position if there is
* a NUL-terminated string in the data (this could be just a NUL terminator).
@@ -1035,7 +1033,7 @@ gst_byte_reader_peek_string_utf8 (const GstByteReader * reader,
* gst_byte_reader_get_string_utf8:
* @reader: a #GstByteReader instance
* @str: (out) (transfer none) (array zero-terminated=1): address of a
- * #gchar pointer varieble in which to store the result
+ * #gchar pointer variable in which to store the result
*
* Returns a constant pointer to the current data position if there is
* a NUL-terminated string in the data (this could be just a NUL terminator),
@@ -1091,7 +1089,7 @@ gst_byte_reader_dup_string_utf##bits (GstByteReader * reader, type ** str) \
* gst_byte_reader_dup_string_utf8:
* @reader: a #GstByteReader instance
* @str: (out) (transfer full) (array zero-terminated=1): address of a
- * #gchar pointer varieble in which to store the result
+ * #gchar pointer variable in which to store the result
*
* Free-function: g_free
*
@@ -1111,7 +1109,7 @@ GST_BYTE_READER_DUP_STRING (8, gchar);
* gst_byte_reader_dup_string_utf16:
* @reader: a #GstByteReader instance
* @str: (out) (transfer full) (array zero-terminated=1): address of a
- * #guint16 pointer varieble in which to store the result
+ * #guint16 pointer variable in which to store the result
*
* Free-function: g_free
*
@@ -1137,7 +1135,7 @@ GST_BYTE_READER_DUP_STRING (16, guint16);
* gst_byte_reader_dup_string_utf32:
* @reader: a #GstByteReader instance
* @str: (out) (transfer full) (array zero-terminated=1): address of a
- * #guint32 pointer varieble in which to store the result
+ * #guint32 pointer variable in which to store the result
*
* Free-function: g_free
*
diff --git a/libs/gst/base/gstbytereader.h b/libs/gst/base/gstbytereader.h
index 6ed0296..8745ef6 100644
--- a/libs/gst/base/gstbytereader.h
+++ b/libs/gst/base/gstbytereader.h
@@ -333,6 +333,9 @@ __GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gdouble,float64_be)
#ifndef GST_BYTE_READER_DISABLE_INLINES
+#define gst_byte_reader_init(reader,data,size) \
+ _gst_byte_reader_init_inline(reader,data,size)
+
#define gst_byte_reader_get_remaining(reader) \
_gst_byte_reader_get_remaining_inline(reader)
@@ -436,6 +439,16 @@ __GST_BYTE_READER_GET_PEEK_BITS_INLINE(64,gdouble,float64_be)
#endif /* GST_BYTE_READER_DISABLE_INLINES */
+static inline void
+_gst_byte_reader_init_inline (GstByteReader * reader, const guint8 * data, guint size)
+{
+ g_return_if_fail (reader != NULL);
+
+ reader->data = data;
+ reader->size = size;
+ reader->byte = 0;
+}
+
static inline gboolean
_gst_byte_reader_dup_data_inline (GstByteReader * reader, guint size, guint8 ** val)
{
diff --git a/libs/gst/base/gstbytewriter-docs.h b/libs/gst/base/gstbytewriter-docs.h
index 562eeae..3cc5962 100644
--- a/libs/gst/base/gstbytewriter-docs.h
+++ b/libs/gst/base/gstbytewriter-docs.h
@@ -258,8 +258,9 @@ void gst_byte_writer_put_data_unchecked (GstByteWriter *writer, const guint8 *da
/**
* gst_byte_writer_fill_unchecked:
* @writer: #GstByteWriter instance
- * @value: Value to be writen
- * @size: Number of bytes to be writen
+ * @value: Value to be written
+ * @size: Number of bytes to be written
+
*
* Writes @size bytes containing @value to @writer without
* checking if there is enough free space available in the byte writer.
diff --git a/libs/gst/base/gstbytewriter.c b/libs/gst/base/gstbytewriter.c
index 2d99480..a30dac6 100644
--- a/libs/gst/base/gstbytewriter.c
+++ b/libs/gst/base/gstbytewriter.c
@@ -661,8 +661,8 @@ CREATE_WRITE_STRING_FUNC (32, guint32);
/**
* gst_byte_writer_fill:
* @writer: #GstByteWriter instance
- * @value: Value to be writen
- * @size: Number of bytes to be writen
+ * @value: Value to be written
+ * @size: Number of bytes to be written
*
* Writes @size bytes containing @value to @writer.
*
diff --git a/libs/gst/base/gstcollectpads.c b/libs/gst/base/gstcollectpads.c
index a30e10a..8f97b71 100644
--- a/libs/gst/base/gstcollectpads.c
+++ b/libs/gst/base/gstcollectpads.c
@@ -49,8 +49,8 @@
* <listitem><para>
* Data can be dequeued from the pad with the gst_collect_pads_pop() method.
* One can peek at the data with the gst_collect_pads_peek() function.
- * These functions will return NULL if the pad received an EOS event. When all
- * pads return NULL from a gst_collect_pads_peek(), the element can emit an EOS
+ * These functions will return %NULL if the pad received an EOS event. When all
+ * pads return %NULL from a gst_collect_pads_peek(), the element can emit an EOS
* event itself.
* </para></listitem>
* <listitem><para>
@@ -65,19 +65,12 @@
* no pad is blocked and the element can finish streaming.
* </para></listitem>
* <listitem><para>
- * gst_collect_pads_collect() and gst_collect_pads_collect_range() can be used by
- * elements that start a #GstTask to drive the collect_pads. This feature is however
- * not yet implemented.
- * </para></listitem>
- * <listitem><para>
* gst_collect_pads_set_waiting() sets a pad to waiting or non-waiting mode.
* CollectPads element is not waiting for data to be collected on non-waiting pads.
* Thus these pads may but need not have data when the callback is called.
* All pads are in waiting mode by default.
* </para></listitem>
* </itemizedlist>
- *
- * Last reviewed on 2011-10-28 (0.10.36)
*/
#ifdef HAVE_CONFIG_H
@@ -132,11 +125,17 @@ struct _GstCollectPadsPrivate
gpointer query_user_data;
GstCollectPadsClipFunction clip_func;
gpointer clip_user_data;
+ GstCollectPadsFlushFunction flush_func;
+ gpointer flush_user_data;
/* no other lock needed */
GMutex evt_lock; /* these make up sort of poor man's event signaling */
GCond evt_cond;
guint32 evt_cookie;
+
+ gboolean seeking;
+ gboolean pending_flush_start;
+ gboolean pending_flush_stop;
};
static void gst_collect_pads_clear (GstCollectPads * pads,
@@ -260,6 +259,13 @@ gst_collect_pads_init (GstCollectPads * pads)
g_mutex_init (&pads->priv->evt_lock);
g_cond_init (&pads->priv->evt_cond);
pads->priv->evt_cookie = 0;
+
+ pads->priv->seeking = FALSE;
+ pads->priv->pending_flush_start = FALSE;
+ pads->priv->pending_flush_stop = FALSE;
+
+ /* clear floating flag */
+ gst_object_ref_sink (pads);
}
static void
@@ -290,7 +296,7 @@ gst_collect_pads_finalize (GObject * object)
*
* MT safe.
*
- * Returns: (transfer full): a new #GstCollectPads, or NULL in case of an error.
+ * Returns: (transfer full): a new #GstCollectPads, or %NULL in case of an error.
*/
GstCollectPads *
gst_collect_pads_new (void)
@@ -318,7 +324,7 @@ gst_collect_pads_set_buffer_function_locked (GstCollectPads * pads,
* @user_data: (closure): user data passed to the function
*
* Set the callback function and user data that will be called with
- * the oldest buffer when all pads have been collected, or NULL on EOS.
+ * the oldest buffer when all pads have been collected, or %NULL on EOS.
* If a buffer is passed, the callback owns a reference and must unref
* it.
*
@@ -522,7 +528,7 @@ gst_collect_pads_clip_running_time (GstCollectPads * pads,
return GST_FLOW_OK;
}
- /**
+/**
* gst_collect_pads_set_clip_function:
* @pads: the collectpads to use
* @clipfunc: clip function to install
@@ -543,6 +549,29 @@ gst_collect_pads_set_clip_function (GstCollectPads * pads,
}
/**
+ * gst_collect_pads_set_flush_function:
+ * @pads: the collectpads to use
+ * @func: flush function to install
+ * @user_data: user data to pass to @func
+ *
+ * Install a flush function that is called when the internal
+ * state of all pads should be flushed as part of flushing seek
+ * handling. See #GstCollectPadsFlushFunction for more info.
+ *
+ * Since: 1.4
+ */
+void
+gst_collect_pads_set_flush_function (GstCollectPads * pads,
+ GstCollectPadsFlushFunction func, gpointer user_data)
+{
+ g_return_if_fail (pads != NULL);
+ g_return_if_fail (GST_IS_COLLECT_PADS (pads));
+
+ pads->priv->flush_func = func;
+ pads->priv->flush_user_data = user_data;
+}
+
+/**
* gst_collect_pads_add_pad:
* @pads: the collectpads to use
* @pad: (transfer none): the pad to add
@@ -577,7 +606,7 @@ gst_collect_pads_set_clip_function (GstCollectPads * pads,
*
* MT safe.
*
- * Returns: a new #GstCollectData to identify the new pad. Or NULL
+ * Returns: a new #GstCollectData to identify the new pad. Or %NULL
* if wrong parameters are supplied.
*/
GstCollectData *
@@ -895,7 +924,7 @@ gst_collect_pads_stop (GstCollectPads * pads)
*
* MT safe.
*
- * Returns: The buffer in @data or NULL if no buffer is queued.
+ * Returns: The buffer in @data or %NULL if no buffer is queued.
* should unref the buffer after usage.
*/
GstBuffer *
@@ -927,7 +956,7 @@ gst_collect_pads_peek (GstCollectPads * pads, GstCollectData * data)
*
* MT safe.
*
- * Returns: (transfer full): The buffer in @data or NULL if no buffer was
+ * Returns: (transfer full): The buffer in @data or %NULL if no buffer was
* queued. You should unref the buffer after usage.
*/
GstBuffer *
@@ -1095,7 +1124,7 @@ gst_collect_pads_flush (GstCollectPads * pads, GstCollectData * data,
* MT safe.
*
* Returns: (transfer full): A sub buffer. The size of the buffer can be less that requested.
- * A return of NULL signals that the pad is end-of-stream.
+ * A return of %NULL signals that the pad is end-of-stream.
* Unref the buffer after use.
*/
GstBuffer *
@@ -1134,7 +1163,7 @@ gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data,
* MT safe.
*
* Returns: A sub buffer. The size of the buffer can be less that requested.
- * A return of NULL signals that the pad is end-of-stream.
+ * A return of %NULL signals that the pad is end-of-stream.
* Unref the buffer after use.
*/
GstBuffer *
@@ -1285,6 +1314,10 @@ gst_collect_pads_check_collected (GstCollectPads * pads)
GST_DEBUG_OBJECT (pads, "All active pads (%d) are EOS, calling %s",
pads->priv->numpads, GST_DEBUG_FUNCPTR_NAME (func));
+ if (G_UNLIKELY (g_atomic_int_compare_and_exchange (&pads->priv->seeking,
+ TRUE, FALSE) == TRUE)) {
+ GST_INFO_OBJECT (pads, "finished seeking");
+ }
do {
flow_ret = func (pads, user_data);
} while (flow_ret == GST_FLOW_OK);
@@ -1299,6 +1332,10 @@ gst_collect_pads_check_collected (GstCollectPads * pads)
pads->priv->queuedpads, pads->priv->eospads, pads->priv->numpads,
GST_DEBUG_FUNCPTR_NAME (func));
+ if (G_UNLIKELY (g_atomic_int_compare_and_exchange (&pads->priv->seeking,
+ TRUE, FALSE) == TRUE)) {
+ GST_INFO_OBJECT (pads, "finished seeking");
+ }
flow_ret = func (pads, user_data);
collected = TRUE;
@@ -1329,7 +1366,7 @@ gst_collect_pads_check_collected (GstCollectPads * pads)
*
* Must be called with STREAM_LOCK.
*
- * Returns TRUE if a pad was set to waiting
+ * Returns %TRUE if a pad was set to waiting
* (from non-waiting state).
*/
static gboolean
@@ -1602,7 +1639,7 @@ gst_collect_pads_clip_time (GstCollectPads * pads, GstCollectData * data,
* @event: event being processed
* @discard: process but do not send event downstream
*
- * Default GstCollectPads event handling that elements should always
+ * Default #GstCollectPads event handling that elements should always
* chain up to to ensure proper operation. Element might however indicate
* event should not be forwarded downstream.
*/
@@ -1625,33 +1662,59 @@ gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data,
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
{
- /* forward event to unblock check_collected */
- GST_DEBUG_OBJECT (pad, "forwarding flush start");
- res = gst_pad_event_default (pad, parent, event);
- event = NULL;
-
- /* now unblock the chain function.
- * no cond per pad, so they all unblock,
- * non-flushing block again */
- GST_COLLECT_PADS_STREAM_LOCK (pads);
- GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_FLUSHING);
- gst_collect_pads_clear (pads, data);
-
- /* cater for possible default muxing functionality */
- if (buffer_func) {
- /* restore to initial state */
- gst_collect_pads_set_waiting (pads, data, TRUE);
- /* if the current pad is affected, reset state, recalculate later */
- if (pads->priv->earliest_data == data) {
- unref_data (data);
- pads->priv->earliest_data = NULL;
- pads->priv->earliest_time = GST_CLOCK_TIME_NONE;
+ if (g_atomic_int_get (&pads->priv->seeking)) {
+ /* drop all but the first FLUSH_STARTs when seeking */
+ if (g_atomic_int_compare_and_exchange (&pads->priv->pending_flush_start,
+ TRUE, FALSE) == FALSE)
+ goto eat;
+
+ /* unblock collect pads */
+ gst_pad_event_default (pad, parent, event);
+ event = NULL;
+
+ GST_COLLECT_PADS_STREAM_LOCK (pads);
+ /* Start flushing. We never call gst_collect_pads_set_flushing (FALSE), we
+ * instead wait until each pad gets its FLUSH_STOP and let that reset the pad to
+ * non-flushing (which happens in gst_collect_pads_event_default).
+ */
+ gst_collect_pads_set_flushing (pads, TRUE);
+
+ if (pads->priv->flush_func)
+ pads->priv->flush_func (pads, pads->priv->flush_user_data);
+
+ g_atomic_int_set (&pads->priv->pending_flush_stop, TRUE);
+ GST_COLLECT_PADS_STREAM_UNLOCK (pads);
+
+ goto eat;
+ } else {
+ /* forward event to unblock check_collected */
+ GST_DEBUG_OBJECT (pad, "forwarding flush start");
+ res = gst_pad_event_default (pad, parent, event);
+ event = NULL;
+
+ /* now unblock the chain function.
+ * no cond per pad, so they all unblock,
+ * non-flushing block again */
+ GST_COLLECT_PADS_STREAM_LOCK (pads);
+ GST_COLLECT_PADS_STATE_SET (data, GST_COLLECT_PADS_STATE_FLUSHING);
+ gst_collect_pads_clear (pads, data);
+
+ /* cater for possible default muxing functionality */
+ if (buffer_func) {
+ /* restore to initial state */
+ gst_collect_pads_set_waiting (pads, data, TRUE);
+ /* if the current pad is affected, reset state, recalculate later */
+ if (pads->priv->earliest_data == data) {
+ unref_data (data);
+ pads->priv->earliest_data = NULL;
+ pads->priv->earliest_time = GST_CLOCK_TIME_NONE;
+ }
}
- }
- GST_COLLECT_PADS_STREAM_UNLOCK (pads);
+ GST_COLLECT_PADS_STREAM_UNLOCK (pads);
- goto eat;
+ goto eat;
+ }
}
case GST_EVENT_FLUSH_STOP:
{
@@ -1669,12 +1732,22 @@ gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data,
if (!GST_COLLECT_PADS_STATE_IS_SET (data,
GST_COLLECT_PADS_STATE_WAITING))
pads->priv->queuedpads++;
- pads->priv->eospads--;
+ if (!g_atomic_int_get (&pads->priv->seeking)) {
+ pads->priv->eospads--;
+ }
GST_COLLECT_PADS_STATE_UNSET (data, GST_COLLECT_PADS_STATE_EOS);
}
GST_COLLECT_PADS_STREAM_UNLOCK (pads);
- goto forward;
+ if (g_atomic_int_get (&pads->priv->seeking)) {
+ if (g_atomic_int_compare_and_exchange (&pads->priv->pending_flush_stop,
+ TRUE, FALSE))
+ goto forward;
+ else
+ goto eat;
+ } else {
+ goto forward;
+ }
}
case GST_EVENT_EOS:
{
@@ -1777,6 +1850,99 @@ forward:
return gst_pad_event_default (pad, parent, event);
}
+typedef struct
+{
+ GstEvent *event;
+ gboolean result;
+} EventData;
+
+static gboolean
+event_forward_func (GstPad * pad, EventData * data)
+{
+ gboolean ret = TRUE;
+ GstPad *peer = gst_pad_get_peer (pad);
+
+ if (peer) {
+ ret = gst_pad_send_event (peer, gst_event_ref (data->event));
+ gst_object_unref (peer);
+ }
+
+ data->result &= ret;
+ /* Always send to all pads */
+ return FALSE;
+}
+
+static gboolean
+forward_event_to_all_sinkpads (GstPad * srcpad, GstEvent * event)
+{
+ EventData data;
+
+ data.event = event;
+ data.result = TRUE;
+
+ gst_pad_forward (srcpad, (GstPadForwardFunction) event_forward_func, &data);
+
+ gst_event_unref (event);
+
+ return data.result;
+}
+
+/**
+ * gst_collect_pads_src_event_default:
+ * @pads: the collectpads to use
+ * @pad: src #GstPad that received the event
+ * @event: event being processed
+ *
+ * Default #GstCollectPads event handling for the src pad of elements.
+ * Elements can chain up to this to let flushing seek event handling
+ * be done by GstCollectPads.
+ *
+ * Since: 1.4
+ */
+gboolean
+gst_collect_pads_src_event_default (GstCollectPads * pads, GstPad * pad,
+ GstEvent * event)
+{
+ GstObject *parent;
+ gboolean res = TRUE;
+
+ parent = GST_OBJECT_PARENT (pad);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_SEEK:{
+ GstSeekFlags flags;
+
+ pads->priv->eospads = 0;
+
+ GST_INFO_OBJECT (pads, "starting seek");
+
+ gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL);
+ if (flags & GST_SEEK_FLAG_FLUSH) {
+ g_atomic_int_set (&pads->priv->seeking, TRUE);
+ g_atomic_int_set (&pads->priv->pending_flush_start, TRUE);
+ /* forward the seek upstream */
+ res = forward_event_to_all_sinkpads (pad, event);
+ event = NULL;
+ if (!res) {
+ g_atomic_int_set (&pads->priv->seeking, FALSE);
+ g_atomic_int_set (&pads->priv->pending_flush_start, FALSE);
+ }
+ }
+
+ GST_INFO_OBJECT (pads, "seek done, result: %d", res);
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (event)
+ res = gst_pad_event_default (pad, parent, event);
+
+ return res;
+}
+
static gboolean
gst_collect_pads_event_default_internal (GstCollectPads * pads,
GstCollectData * data, GstEvent * event, gpointer user_data)
@@ -1844,7 +2010,7 @@ pad_removed:
* @query: query being processed
* @discard: process but do not send event downstream
*
- * Default GstCollectPads query handling that elements should always
+ * Default #GstCollectPads query handling that elements should always
* chain up to to ensure proper operation. Element might however indicate
* query should not be forwarded downstream.
*/
diff --git a/libs/gst/base/gstcollectpads.h b/libs/gst/base/gstcollectpads.h
index 4c99d58..0ba2dee 100644
--- a/libs/gst/base/gstcollectpads.h
+++ b/libs/gst/base/gstcollectpads.h
@@ -134,27 +134,27 @@ struct _GstCollectData
/**
* GstCollectPadsFunction:
- * @pads: the #GstCollectPads that trigered the callback
+ * @pads: the #GstCollectPads that triggered the callback
* @user_data: user data passed to gst_collect_pads_set_function()
*
* A function that will be called when all pads have received data.
*
- * Returns: #GST_FLOW_OK for success
+ * Returns: %GST_FLOW_OK for success
*/
typedef GstFlowReturn (*GstCollectPadsFunction) (GstCollectPads *pads, gpointer user_data);
/**
* GstCollectPadsBufferFunction:
- * @pads: the #GstCollectPads that trigered the callback
+ * @pads: the #GstCollectPads that triggered the callback
* @data: the #GstCollectData of pad that has received the buffer
* @buffer: (transfer full): the #GstBuffer
* @user_data: user data passed to gst_collect_pads_set_buffer_function()
*
* A function that will be called when a (considered oldest) buffer can be muxed.
- * If all pads have reached EOS, this function is called with NULL @buffer
- * and NULL @data.
+ * If all pads have reached EOS, this function is called with %NULL @buffer
+ * and %NULL @data.
*
- * Returns: #GST_FLOW_OK for success
+ * Returns: %GST_FLOW_OK for success
*/
typedef GstFlowReturn (*GstCollectPadsBufferFunction) (GstCollectPads *pads, GstCollectData *data,
GstBuffer *buffer, gpointer user_data);
@@ -172,7 +172,7 @@ typedef GstFlowReturn (*GstCollectPadsBufferFunction) (GstCollectPads *pads, Gst
*
* Returns: Integer less than zero when first timestamp is deemed older than the second one.
* Zero if the timestamps are deemed equally old.
- * Integer greate than zero when second timestamp is deemed older than the first one.
+ * Integer greater than zero when second timestamp is deemed older than the first one.
*/
typedef gint (*GstCollectPadsCompareFunction) (GstCollectPads *pads,
GstCollectData * data1, GstClockTime timestamp1,
@@ -181,7 +181,7 @@ typedef gint (*GstCollectPadsCompareFunction) (GstCollectPads *pads,
/**
* GstCollectPadsEventFunction:
- * @pads: the #GstCollectPads that trigered the callback
+ * @pads: the #GstCollectPads that triggered the callback
* @pad: the #GstPad that received an event
* @event: the #GstEvent received
* @user_data: user data passed to gst_collect_pads_set_event_function()
@@ -199,7 +199,7 @@ typedef gboolean (*GstCollectPadsEventFunction) (GstCollectPads *pads, Gs
/**
* GstCollectPadsQueryFunction:
- * @pads: the #GstCollectPads that trigered the callback
+ * @pads: the #GstCollectPads that triggered the callback
* @pad: the #GstPad that received an event
* @query: the #GstEvent received
* @user_data: user data passed to gst_collect_pads_set_query_function()
@@ -222,7 +222,7 @@ typedef gboolean (*GstCollectPadsQueryFunction) (GstCollectPads *pads, Gs
* @user_data: user data
*
* A function that will be called when @inbuffer is received on the pad managed
- * by @data in the collecpad object @pads.
+ * by @data in the collectpad object @pads.
*
* The function should use the segment of @data and the negotiated media type on
* the pad to perform clipping of @inbuffer.
@@ -236,6 +236,23 @@ typedef GstFlowReturn (*GstCollectPadsClipFunction) (GstCollectPads *pads, GstCo
GstBuffer *inbuffer, GstBuffer **outbuffer,
gpointer user_data);
+
+/**
+ * GstCollectPadsFlushFunction:
+ * @pads: a #GstCollectPads
+ * @user_data: user data
+ *
+ * A function that will be called while processing a flushing seek event.
+ *
+ * The function should flush any internal state of the element and the state of
+ * all the pads. It should clear only the state not directly managed by the
+ * @pads object. It is therefore not necessary to call
+ * gst_collect_pads_set_flushing nor gst_collect_pads_clear from this function.
+ *
+ * Since: 1.4
+ */
+typedef void (*GstCollectPadsFlushFunction) (GstCollectPads *pads, gpointer user_data);
+
/**
* GST_COLLECT_PADS_GET_STREAM_LOCK:
* @pads: a #GstCollectPads
@@ -311,6 +328,9 @@ void gst_collect_pads_set_compare_function (GstCollectPads *pads,
void gst_collect_pads_set_clip_function (GstCollectPads *pads,
GstCollectPadsClipFunction clipfunc,
gpointer user_data);
+void gst_collect_pads_set_flush_function (GstCollectPads *pads,
+ GstCollectPadsFlushFunction func,
+ gpointer user_data);
/* pad management */
GstCollectData* gst_collect_pads_add_pad (GstCollectPads *pads, GstPad *pad, guint size,
@@ -349,6 +369,8 @@ GstFlowReturn gst_collect_pads_clip_running_time (GstCollectPads * pads,
/* default handlers */
gboolean gst_collect_pads_event_default (GstCollectPads * pads, GstCollectData * data,
GstEvent * event, gboolean discard);
+gboolean gst_collect_pads_src_event_default (GstCollectPads * pads, GstPad * pad,
+ GstEvent * event);
gboolean gst_collect_pads_query_default (GstCollectPads * pads, GstCollectData * data,
GstQuery * query, gboolean discard);
diff --git a/libs/gst/base/gstdataqueue.c b/libs/gst/base/gstdataqueue.c
index 0c46f0c..e34b265 100644
--- a/libs/gst/base/gstdataqueue.c
+++ b/libs/gst/base/gstdataqueue.c
@@ -209,12 +209,13 @@ gst_data_queue_init (GstDataQueue * queue)
}
/**
- * gst_data_queue_new:
+ * gst_data_queue_new: (skip)
* @checkfull: the callback used to tell if the element considers the queue full
* or not.
* @fullcallback: the callback which will be called when the queue is considered full.
* @emptycallback: the callback which will be called when the queue is considered empty.
- * @checkdata: a #gpointer that will be given in the @checkfull callback.
+ * @checkdata: a #gpointer that will be passed to the @checkfull, @fullcallback,
+ * and @emptycallback callbacks.
*
* Creates a new #GstDataQueue. The difference with @gst_data_queue_new is that it will
* not emit the 'full' and 'empty' signals, but instead calling directly @fullcallback
@@ -222,7 +223,7 @@ gst_data_queue_init (GstDataQueue * queue)
*
* Returns: a new #GstDataQueue.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
GstDataQueue *
gst_data_queue_new (GstDataQueueCheckFullFunction checkfull,
@@ -318,7 +319,7 @@ gst_data_queue_locked_is_full (GstDataQueue * queue)
* #gst_data_queue_pop will be released.
* MT safe.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
void
gst_data_queue_flush (GstDataQueue * queue)
@@ -336,9 +337,9 @@ gst_data_queue_flush (GstDataQueue * queue)
* Queries if there are any items in the @queue.
* MT safe.
*
- * Returns: #TRUE if @queue is empty.
+ * Returns: %TRUE if @queue is empty.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gboolean
gst_data_queue_is_empty (GstDataQueue * queue)
@@ -360,9 +361,9 @@ gst_data_queue_is_empty (GstDataQueue * queue)
* #GstDataQueueCheckFullFunction registered with @queue.
* MT safe.
*
- * Returns: #TRUE if @queue is full.
+ * Returns: %TRUE if @queue is full.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gboolean
gst_data_queue_is_full (GstDataQueue * queue)
@@ -381,15 +382,15 @@ gst_data_queue_is_full (GstDataQueue * queue)
* @queue: a #GstDataQueue.
* @flushing: a #gboolean stating if the queue will be flushing or not.
*
- * Sets the queue to flushing state if @flushing is #TRUE. If set to flushing
+ * Sets the queue to flushing state if @flushing is %TRUE. If set to flushing
* state, any incoming data on the @queue will be discarded. Any call currently
* blocking on #gst_data_queue_push or #gst_data_queue_pop will return straight
- * away with a return value of #FALSE. While the @queue is in flushing state,
- * all calls to those two functions will return #FALSE.
+ * away with a return value of %FALSE. While the @queue is in flushing state,
+ * all calls to those two functions will return %FALSE.
*
* MT Safe.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
void
gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing)
@@ -436,12 +437,12 @@ gst_data_queue_push_force_unlocked (GstDataQueue * queue,
*
* Note that this function has slightly different semantics than gst_pad_push()
* and gst_pad_push_event(): this function only takes ownership of @item and
- * the #GstMiniObject contained in @item if the push was successful. If FALSE
+ * the #GstMiniObject contained in @item if the push was successful. If %FALSE
* is returned, the caller is responsible for freeing @item and its contents.
*
- * Returns: #TRUE if the @item was successfully pushed on the @queue.
+ * Returns: %TRUE if the @item was successfully pushed on the @queue.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gboolean
gst_data_queue_push_force (GstDataQueue * queue, GstDataQueueItem * item)
@@ -484,12 +485,12 @@ flushing:
*
* Note that this function has slightly different semantics than gst_pad_push()
* and gst_pad_push_event(): this function only takes ownership of @item and
- * the #GstMiniObject contained in @item if the push was successful. If FALSE
+ * the #GstMiniObject contained in @item if the push was successful. If %FALSE
* is returned, the caller is responsible for freeing @item and its contents.
*
- * Returns: #TRUE if the @item was successfully pushed on the @queue.
+ * Returns: %TRUE if the @item was successfully pushed on the @queue.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gboolean
gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item)
@@ -566,9 +567,9 @@ _gst_data_queue_wait_non_empty (GstDataQueue * queue)
* @queue is set to the flushing state.
* MT safe.
*
- * Returns: #TRUE if an @item was successfully retrieved from the @queue.
+ * Returns: %TRUE if an @item was successfully retrieved from the @queue.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gboolean
gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item)
@@ -636,9 +637,9 @@ is_of_type (gconstpointer a, gconstpointer b)
* one item is available, OR the @queue is set to the flushing state.
* MT safe.
*
- * Returns: #TRUE if an @item was successfully retrieved from the @queue.
+ * Returns: %TRUE if an @item was successfully retrieved from the @queue.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gboolean
gst_data_queue_peek (GstDataQueue * queue, GstDataQueueItem ** item)
@@ -688,9 +689,9 @@ flushing:
*
* Pop and unref the head-most #GstMiniObject with the given #GType.
*
- * Returns: TRUE if an element was removed.
+ * Returns: %TRUE if an element was removed.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gboolean
gst_data_queue_drop_head (GstDataQueue * queue, GType type)
@@ -731,12 +732,12 @@ done:
/**
* gst_data_queue_limits_changed:
- * @queue: The #GstDataQueue
+ * @queue: The #GstDataQueue
*
* Inform the queue that the limits for the fullness check have changed and that
- * any blocking gst_data_queue_push() should be unblocked to recheck the limts.
+ * any blocking gst_data_queue_push() should be unblocked to recheck the limits.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
void
gst_data_queue_limits_changed (GstDataQueue * queue)
@@ -760,7 +761,7 @@ gst_data_queue_limits_changed (GstDataQueue * queue)
*
* Get the current level of the queue.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
void
gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize * level)
diff --git a/libs/gst/base/gstdataqueue.h b/libs/gst/base/gstdataqueue.h
index c707c8b..7350c42 100644
--- a/libs/gst/base/gstdataqueue.h
+++ b/libs/gst/base/gstdataqueue.h
@@ -47,8 +47,8 @@ typedef struct _GstDataQueuePrivate GstDataQueuePrivate;
* @object: the #GstMiniObject to queue.
* @size: the size in bytes of the miniobject.
* @duration: the duration in #GstClockTime of the miniobject. Can not be
- * #GST_CLOCK_TIME_NONE.
- * @visible: #TRUE if @object should be considered as a visible object.
+ * %GST_CLOCK_TIME_NONE.
+ * @visible: %TRUE if @object should be considered as a visible object.
* @destroy: The #GDestroyNotify function to use to free the #GstDataQueueItem.
* This function should also drop the reference to @object the owner of the
* #GstDataQueueItem is assumed to hold.
@@ -97,7 +97,7 @@ struct _GstDataQueueSize
* The prototype of the function used to inform the queue that it should be
* considered as full.
*
- * Returns: #TRUE if the queue should be considered full.
+ * Returns: %TRUE if the queue should be considered full.
*/
typedef gboolean (*GstDataQueueCheckFullFunction) (GstDataQueue * queue,
guint visible, guint bytes, guint64 time, gpointer checkdata);
diff --git a/libs/gst/base/gstflowcombiner.c b/libs/gst/base/gstflowcombiner.c
new file mode 100644
index 0000000..e21f6c2
--- /dev/null
+++ b/libs/gst/base/gstflowcombiner.c
@@ -0,0 +1,248 @@
+/* GStreamer
+ *
+ * Copyright (C) 2014 Samsung Electronics. All rights reserved.
+ * Author: Thiago Santos <ts.santos@sisa.samsung.com>
+ *
+ * gstflowcombiner.c: utility to combine multiple flow returns into a single one
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstflowcombiner
+ * @short_description: Utility to combine multiple flow returns into one
+ *
+ * Utility struct to help handling #GstFlowReturn combination. Useful for
+ * #GstElement<!-- -->s that have multiple source pads and need to combine
+ * the different #GstFlowReturn for those pads.
+ *
+ * #GstFlowCombiner works by using the last #GstFlowReturn for all #GstPad
+ * it has in its list and computes the combined return value and provides
+ * it to the caller.
+ *
+ * To add a new pad to the #GstFlowCombiner use gst_flow_combiner_add_pad().
+ * The new #GstPad is stored with a default value of %GST_FLOW_OK.
+ *
+ * In case you want a #GstPad to be removed, use gst_flow_combiner_remove_pad().
+ *
+ * Please be aware that this struct isn't thread safe as its designed to be
+ * used by demuxers, those usually will have a single thread operating it.
+ *
+ * None of these functions will take refs on the passed #GstPad<!-- -->s, it
+ * is the caller's responsibility to make sure that the #GstPad exists as long
+ * as this struct exists.
+ *
+ * Aside from reducing the user's code size, the main advantage of using this
+ * helper struct is to follow the standard rules for #GstFlowReturn combination.
+ * These rules are:
+ *
+ * * %GST_FLOW_EOS: only if all returns are EOS too
+ * * %GST_FLOW_NOT_LINKED: only if all returns are NOT_LINKED too
+ * * %GST_FLOW_ERROR or below: if at least one returns an error return
+ * * %GST_FLOW_NOT_NEGOTIATED: if at least one returns a not-negotiated return
+ * * %GST_FLOW_FLUSHING: if at least one returns flushing
+ * * %GST_FLOW_OK: otherwise
+ *
+ * %GST_FLOW_ERROR or below, GST_FLOW_NOT_NEGOTIATED and GST_FLOW_FLUSHING are
+ * returned immediatelly from the gst_flow_combiner_update_flow() function.
+ *
+ * Since: 1.4
+ */
+
+#include <gst/gst.h>
+#include "gstflowcombiner.h"
+
+struct _GstFlowCombiner
+{
+ GQueue pads;
+
+ GstFlowReturn last_ret;
+ volatile gint ref_count;
+};
+
+static GstFlowCombiner *gst_flow_combiner_ref (GstFlowCombiner * combiner);
+static void gst_flow_combiner_unref (GstFlowCombiner * combiner);
+
+G_DEFINE_BOXED_TYPE (GstFlowCombiner, gst_flow_combiner,
+ (GBoxedCopyFunc) gst_flow_combiner_ref,
+ (GBoxedFreeFunc) gst_flow_combiner_unref);
+
+/**
+ * gst_flow_combiner_new:
+ *
+ * Creates a new #GstFlowCombiner, use gst_flow_combiner_free() to free it.
+ *
+ * Returns: A new #GstFlowCombiner
+ * Since: 1.4
+ */
+GstFlowCombiner *
+gst_flow_combiner_new (void)
+{
+ GstFlowCombiner *combiner = g_slice_new (GstFlowCombiner);
+
+ g_queue_init (&combiner->pads);
+ combiner->last_ret = GST_FLOW_OK;
+ combiner->ref_count = 1;
+
+ return combiner;
+}
+
+/**
+ * gst_flow_combiner_free:
+ * @combiner: the #GstFlowCombiner to free
+ *
+ * Frees a #GstFlowCombiner struct and all its internal data.
+ *
+ * Since: 1.4
+ */
+void
+gst_flow_combiner_free (GstFlowCombiner * combiner)
+{
+ gst_flow_combiner_unref (combiner);
+}
+
+static GstFlowCombiner *
+gst_flow_combiner_ref (GstFlowCombiner * combiner)
+{
+ g_return_val_if_fail (combiner != NULL, NULL);
+
+ g_atomic_int_inc (&combiner->ref_count);
+
+ return combiner;
+}
+
+static void
+gst_flow_combiner_unref (GstFlowCombiner * combiner)
+{
+ g_return_if_fail (combiner != NULL);
+ g_return_if_fail (combiner->ref_count > 0);
+
+ if (g_atomic_int_dec_and_test (&combiner->ref_count)) {
+ GstPad *pad;
+
+ while ((pad = g_queue_pop_head (&combiner->pads)))
+ gst_object_unref (pad);
+
+ g_slice_free (GstFlowCombiner, combiner);
+ }
+}
+
+static GstFlowReturn
+gst_flow_combiner_get_flow (GstFlowCombiner * combiner)
+{
+ GstFlowReturn cret = GST_FLOW_OK;
+ gboolean all_eos = TRUE;
+ gboolean all_notlinked = TRUE;
+ GList *iter;
+
+ GST_DEBUG ("Combining flow returns");
+
+ for (iter = combiner->pads.head; iter; iter = iter->next) {
+ GstFlowReturn fret = GST_PAD_LAST_FLOW_RETURN (iter->data);
+
+ if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING) {
+ GST_DEBUG ("Error flow return found, returning");
+ cret = fret;
+ goto done;
+ }
+
+ if (fret != GST_FLOW_NOT_LINKED) {
+ all_notlinked = FALSE;
+ if (fret != GST_FLOW_EOS)
+ all_eos = FALSE;
+ }
+ }
+ if (all_notlinked)
+ cret = GST_FLOW_NOT_LINKED;
+ else if (all_eos)
+ cret = GST_FLOW_EOS;
+
+done:
+ GST_DEBUG ("Combined flow return: %s (%d)", gst_flow_get_name (cret), cret);
+ return cret;
+}
+
+/**
+ * gst_flow_combiner_update_flow:
+ * @combiner: the #GstFlowCombiner
+ * @fret: the latest #GstFlowReturn received for a pad in this #GstFlowCombiner
+ *
+ * Computes the combined flow return for the pads in it.
+ *
+ * The #GstFlowReturn paramter should be the last flow return update for a pad
+ * in this #GstFlowCombiner. It will use this value to be able to shortcut some
+ * combinations and avoid looking over all pads again. e.g. The last combined
+ * return is the same as the latest obtained #GstFlowReturn.
+ *
+ * Returns: The combined #GstFlowReturn
+ * Since: 1.4
+ */
+GstFlowReturn
+gst_flow_combiner_update_flow (GstFlowCombiner * combiner, GstFlowReturn fret)
+{
+ GstFlowReturn ret;
+
+ g_return_val_if_fail (combiner != NULL, GST_FLOW_ERROR);
+
+ if (combiner->last_ret == fret) {
+ return fret;
+ }
+
+ if (fret <= GST_FLOW_NOT_NEGOTIATED || fret == GST_FLOW_FLUSHING) {
+ ret = fret;
+ } else {
+ ret = gst_flow_combiner_get_flow (combiner);
+ }
+ combiner->last_ret = ret;
+ return ret;
+}
+
+/**
+ * gst_flow_combiner_add_pad:
+ * @combiner: the #GstFlowCombiner
+ * @pad: (transfer none): the #GstPad that is being added
+ *
+ * Adds a new #GstPad to the #GstFlowCombiner.
+ *
+ * Since: 1.4
+ */
+void
+gst_flow_combiner_add_pad (GstFlowCombiner * combiner, GstPad * pad)
+{
+ g_return_if_fail (combiner != NULL);
+ g_return_if_fail (pad != NULL);
+
+ g_queue_push_head (&combiner->pads, gst_object_ref (pad));
+}
+
+/**
+ * gst_flow_combiner_remove_pad:
+ * @combiner: the #GstFlowCombiner
+ * @pad: (transfer none): the #GstPad to remove
+ *
+ * Removes a #GstPad from the #GstFlowCombiner.
+ *
+ * Since: 1.4
+ */
+void
+gst_flow_combiner_remove_pad (GstFlowCombiner * combiner, GstPad * pad)
+{
+ g_return_if_fail (combiner != NULL);
+ g_return_if_fail (pad != NULL);
+
+ if (g_queue_remove (&combiner->pads, pad))
+ gst_object_unref (pad);
+}
diff --git a/libs/gst/base/gstflowcombiner.h b/libs/gst/base/gstflowcombiner.h
new file mode 100644
index 0000000..43c37e3
--- /dev/null
+++ b/libs/gst/base/gstflowcombiner.h
@@ -0,0 +1,58 @@
+/* GStreamer
+ *
+ * Copyright (C) 2014 Samsung Electronics. All rights reserved.
+ * Author: Thiago Santos <ts.santos@sisa.samsung.com>
+ *
+ * gstflowcombiner.h: utility to combine multiple flow returns into a single one
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef __GST_FLOW_COMBINER_H__
+#define __GST_FLOW_COMBINER_H__
+
+#include <glib.h>
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_FLOW_COMBINER gst_flow_combiner_get_type()
+
+/**
+ * GstFlowCombiner:
+ *
+ * Opaque helper structure to aggregate flow returns.
+ *
+ * Since: 1.4
+ */
+typedef struct _GstFlowCombiner GstFlowCombiner;
+
+GstFlowCombiner * gst_flow_combiner_new (void);
+
+void gst_flow_combiner_free (GstFlowCombiner * combiner);
+
+GstFlowReturn gst_flow_combiner_update_flow (GstFlowCombiner * combiner, GstFlowReturn fret);
+
+void gst_flow_combiner_add_pad (GstFlowCombiner * combiner, GstPad * pad);
+
+void gst_flow_combiner_remove_pad (GstFlowCombiner * combiner, GstPad * pad);
+
+GType gst_flow_combiner_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_FLOW_COMBINER_H__ */
diff --git a/libs/gst/base/gstindex.c b/libs/gst/base/gstindex.c
index 3786e95..b614d2c 100644
--- a/libs/gst/base/gstindex.c
+++ b/libs/gst/base/gstindex.c
@@ -25,7 +25,7 @@
* @short_description: Generate indexes on objects
* @see_also: #GstIndexFactory
*
- * GstIndex is used to generate a stream index of one or more elements
+ * #GstIndex is used to generate a stream index of one or more elements
* in a pipeline.
*
* Elements will overload the set_index and get_index virtual methods in
@@ -368,7 +368,7 @@ gst_index_new_group (GstIndex * index)
*
* Set the current groupnumber to the given argument.
*
- * Returns: TRUE if the operation succeeded, FALSE if the group
+ * Returns: %TRUE if the operation succeeded, %FALSE if the group
* did not exist.
*/
gboolean
@@ -571,7 +571,7 @@ gst_index_entry_free (GstIndexEntry * entry)
* @format: the format to add to the index
*
* Adds a format entry into the index. This function is
- * used to map dynamic GstFormat ids to their original
+ * used to map dynamic #GstFormat ids to their original
* format key.
*
* Free-function: gst_index_entry_free
@@ -676,7 +676,7 @@ gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
/**
* gst_index_get_writer_id:
* @index: the index to get a unique write id for
- * @writer: the GstObject to allocate an id for
+ * @writer: the #GstObject to allocate an id for
* @id: a pointer to a gint to hold the id
*
* Before entries can be added to the index, a writer
@@ -688,12 +688,12 @@ gst_index_gtype_resolver (GstIndex * index, GstObject * writer,
* in the index.
*
* <note>
- * The caller must not hold @writer's #GST_OBJECT_LOCK, as the default
+ * The caller must not hold @writer's GST_OBJECT_LOCK(), as the default
* resolver may call functions that take the object lock as well, and
* the lock is not recursive.
* </note>
*
- * Returns: TRUE if the writer would be mapped to an id.
+ * Returns: %TRUE if the writer would be mapped to an id.
*/
gboolean
gst_index_get_writer_id (GstIndex * index, GstObject * writer, gint * id)
@@ -775,7 +775,7 @@ gst_index_add_entry (GstIndex * index, GstIndexEntry * entry)
* @id: the id of the index writer
* @flags: optinal flags for this entry
* @n: number of associations
- * @list: list of associations
+ * @list: (array length=n): list of associations
*
* Associate given format/value pairs with each other.
*
@@ -918,7 +918,7 @@ gst_index_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
*
* Finds the given format/value in the index
*
- * Returns: the entry associated with the value or NULL if the
+ * Returns: the entry associated with the value or %NULL if the
* value was not found.
*/
GstIndexEntry *
@@ -949,7 +949,7 @@ gst_index_get_assoc_entry (GstIndex * index, gint id,
* Finds the given format/value in the index with the given
* compare function and user_data.
*
- * Returns: the entry associated with the value or NULL if the
+ * Returns: the entry associated with the value or %NULL if the
* value was not found.
*/
GstIndexEntry *
@@ -981,7 +981,7 @@ gst_index_get_assoc_entry_full (GstIndex * index, gint id,
*
* Gets alternative formats associated with the indexentry.
*
- * Returns: TRUE if there was a value associated with the given
+ * Returns: %TRUE if there was a value associated with the given
* format.
*/
gboolean
diff --git a/libs/gst/base/gstpushsrc.c b/libs/gst/base/gstpushsrc.c
index f89fa0a..7af8147 100644
--- a/libs/gst/base/gstpushsrc.c
+++ b/libs/gst/base/gstpushsrc.c
@@ -44,8 +44,6 @@
*
* Seeking, flushing, scheduling and sync is all handled by this
* base class.
- *
- * Last reviewed on 2006-07-04 (0.10.9)
*/
#ifdef HAVE_CONFIG_H
diff --git a/libs/gst/base/gstqueuearray.c b/libs/gst/base/gstqueuearray.c
index 4b83959..d37535d 100644
--- a/libs/gst/base/gstqueuearray.c
+++ b/libs/gst/base/gstqueuearray.c
@@ -25,7 +25,7 @@
*
* #GstQueueArray is an object that provides standard queue functionality
* based on an array instead of linked lists. This reduces the overhead
- * caused by memory managment by a large factor.
+ * caused by memory management by a large factor.
*/
@@ -52,7 +52,7 @@ struct _GstQueueArray
*
* Returns: a new #GstQueueArray object
*
- * Since: 1.2.0
+ * Since: 1.2
*/
GstQueueArray *
gst_queue_array_new (guint initial_size)
@@ -75,7 +75,7 @@ gst_queue_array_new (guint initial_size)
*
* Frees queue @array and all memory associated to it.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
void
gst_queue_array_free (GstQueueArray * array)
@@ -93,7 +93,7 @@ gst_queue_array_free (GstQueueArray * array)
*
* Returns: The head of the queue
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gpointer
gst_queue_array_pop_head (GstQueueArray * array)
@@ -111,7 +111,7 @@ gst_queue_array_pop_head (GstQueueArray * array)
}
/**
- * gst_queue_array_pop_head:
+ * gst_queue_array_peek_head:
* @array: a #GstQueueArray object
*
* Returns and head of the queue @array and does not
@@ -119,7 +119,7 @@ gst_queue_array_pop_head (GstQueueArray * array)
*
* Returns: The head of the queue
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gpointer
gst_queue_array_peek_head (GstQueueArray * array)
@@ -137,7 +137,7 @@ gst_queue_array_peek_head (GstQueueArray * array)
*
* Pushes @data to the tail of the queue @array.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
void
gst_queue_array_push_tail (GstQueueArray * array, gpointer data)
@@ -145,7 +145,7 @@ gst_queue_array_push_tail (GstQueueArray * array, gpointer data)
/* Check if we need to make room */
if (G_UNLIKELY (array->length == array->size)) {
/* newsize is 50% bigger */
- guint newsize = (3 * array->size) / 2;
+ guint newsize = MAX ((3 * array->size) / 2, array->size + 1);
/* copy over data */
if (array->tail != 0) {
@@ -190,7 +190,7 @@ gst_queue_array_push_tail (GstQueueArray * array, gpointer data)
*
* Returns: %TRUE if the queue @array is empty
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gboolean
gst_queue_array_is_empty (GstQueueArray * array)
@@ -207,7 +207,7 @@ gst_queue_array_is_empty (GstQueueArray * array)
*
* Returns: the dropped element
*
- * Since: 1.2.0
+ * Since: 1.2
*/
gpointer
gst_queue_array_drop_element (GstQueueArray * array, guint idx)
@@ -297,11 +297,11 @@ gst_queue_array_drop_element (GstQueueArray * array, guint idx)
* Note that the index is not 0-based, but an internal index number with a
* random offset. The index can be used in connection with
* gst_queue_array_drop_element(). FIXME: return index 0-based and make
- * _drop_element() take a 0-based index.
+ * gst_queue_array_drop_element() take a 0-based index.
*
* Returns: Index of the found element or -1 if nothing was found.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
guint
gst_queue_array_find (GstQueueArray * array, GCompareFunc func, gpointer data)
@@ -332,7 +332,7 @@ gst_queue_array_find (GstQueueArray * array, GCompareFunc func, gpointer data)
*
* Returns: the length of the queue @array.
*
- * Since: 1.2.0
+ * Since: 1.2
*/
guint
gst_queue_array_get_length (GstQueueArray * array)
diff --git a/libs/gst/base/gsttypefindhelper.c b/libs/gst/base/gsttypefindhelper.c
index 5f30c8c..1a0d327 100644
--- a/libs/gst/base/gsttypefindhelper.c
+++ b/libs/gst/base/gsttypefindhelper.c
@@ -163,7 +163,7 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
#endif
/* getrange might silently return shortened buffers at the end of a file,
- * we must, however, always return either the full requested data or NULL */
+ * we must, however, always return either the full requested data or %NULL */
buf_offset = GST_BUFFER_OFFSET (buffer);
buf_size = gst_buffer_get_size (buffer);
@@ -246,13 +246,13 @@ helper_find_get_length (gpointer data)
/**
* gst_type_find_helper_get_range:
* @obj: A #GstObject that will be passed as first argument to @func
- * @parent: (allow-none): the parent of @obj or NULL
+ * @parent: (allow-none): the parent of @obj or %NULL
* @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
* be used to access data at random offsets when doing the typefinding
* @size: The length in bytes
* @extension: extension of the media
* @prob: (out) (allow-none): location to store the probability of the found
- * caps, or #NULL
+ * caps, or %NULL
*
* Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
* however, this function will use the specified function @func to obtain the
@@ -263,14 +263,14 @@ helper_find_get_length (gpointer data)
* callback can then call the upstream peer pad with offsets adjusted for the
* tag size, for example).
*
- * When @extension is not NULL, this function will first try the typefind
+ * When @extension is not %NULL, this function will first try the typefind
* functions for the given extension, which might speed up the typefinding
* in many cases.
*
* Free-function: gst_caps_unref
*
* Returns: (transfer full): the #GstCaps corresponding to the data stream.
- * Returns #NULL if no #GstCaps matches the data stream.
+ * Returns %NULL if no #GstCaps matches the data stream.
*/
GstCaps *
gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
@@ -389,7 +389,7 @@ gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
* Free-function: gst_caps_unref
*
* Returns: (transfer full): the #GstCaps corresponding to the data stream.
- * Returns #NULL if no #GstCaps matches the data stream.
+ * Returns %NULL if no #GstCaps matches the data stream.
*/
GstCaps *
@@ -480,26 +480,26 @@ buf_helper_find_suggest (gpointer data, GstTypeFindProbability probability,
/**
* gst_type_find_helper_for_data:
- * @obj: (allow-none): object doing the typefinding, or NULL (used for logging)
+ * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
* @data: (in) (transfer none): a pointer with data to typefind
* @size: (in) (transfer none): the size of @data
* @prob: (out) (allow-none): location to store the probability of the found
- * caps, or #NULL
+ * caps, or %NULL
*
* Tries to find what type of data is contained in the given @data, the
* assumption being that the data represents the beginning of the stream or
* file.
*
* All available typefinders will be called on the data in order of rank. If
- * a typefinding function returns a probability of #GST_TYPE_FIND_MAXIMUM,
+ * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM,
* typefinding is stopped immediately and the found caps will be returned
* right away. Otherwise, all available typefind functions will the tried,
- * and the caps with the highest probability will be returned, or #NULL if
+ * and the caps with the highest probability will be returned, or %NULL if
* the content of @data could not be identified.
*
* Free-function: gst_caps_unref
*
- * Returns: (transfer full): the #GstCaps corresponding to the data, or #NULL
+ * Returns: (transfer full): the #GstCaps corresponding to the data, or %NULL
* if no type could be found. The caller should free the caps returned
* with gst_caps_unref().
*/
@@ -552,25 +552,25 @@ gst_type_find_helper_for_data (GstObject * obj, const guint8 * data, gsize size,
/**
* gst_type_find_helper_for_buffer:
- * @obj: (allow-none): object doing the typefinding, or NULL (used for logging)
+ * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
* @buf: (in) (transfer none): a #GstBuffer with data to typefind
* @prob: (out) (allow-none): location to store the probability of the found
- * caps, or #NULL
+ * caps, or %NULL
*
* Tries to find what type of data is contained in the given #GstBuffer, the
* assumption being that the buffer represents the beginning of the stream or
* file.
*
* All available typefinders will be called on the data in order of rank. If
- * a typefinding function returns a probability of #GST_TYPE_FIND_MAXIMUM,
+ * a typefinding function returns a probability of %GST_TYPE_FIND_MAXIMUM,
* typefinding is stopped immediately and the found caps will be returned
* right away. Otherwise, all available typefind functions will the tried,
- * and the caps with the highest probability will be returned, or #NULL if
+ * and the caps with the highest probability will be returned, or %NULL if
* the content of the buffer could not be identified.
*
* Free-function: gst_caps_unref
*
- * Returns: (transfer full): the #GstCaps corresponding to the data, or #NULL
+ * Returns: (transfer full): the #GstCaps corresponding to the data, or %NULL
* if no type could be found. The caller should free the caps returned
* with gst_caps_unref().
*/
@@ -596,7 +596,7 @@ gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
/**
* gst_type_find_helper_for_extension:
- * @obj: (allow-none): object doing the typefinding, or NULL (used for logging)
+ * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
* @extension: an extension
*
* Tries to find the best #GstCaps associated with @extension.
@@ -608,7 +608,7 @@ gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
* Free-function: gst_caps_unref
*
* Returns: (transfer full): the #GstCaps corresponding to @extension, or
- * #NULL if no type could be found. The caller should free the caps
+ * %NULL if no type could be found. The caller should free the caps
* returned with gst_caps_unref().
*/
GstCaps *
diff --git a/libs/gst/base/gsttypefindhelper.h b/libs/gst/base/gsttypefindhelper.h
index 9447f9b..6770e4f 100644
--- a/libs/gst/base/gsttypefindhelper.h
+++ b/libs/gst/base/gsttypefindhelper.h
@@ -44,7 +44,7 @@ GstCaps * gst_type_find_helper_for_extension (GstObject * obj,
/**
* GstTypeFindHelperGetRangeFunction:
* @obj: a #GstObject that will handle the getrange request
- * @parent: (allow-none): the parent of @obj or NULL
+ * @parent: (allow-none): the parent of @obj or %NULL
* @offset: the offset of the range
* @length: the length of the range
* @buffer: a memory location to hold the result buffer
diff --git a/libs/gst/check/Makefile.am b/libs/gst/check/Makefile.am
index 155bff8..1389270 100644
--- a/libs/gst/check/Makefile.am
+++ b/libs/gst/check/Makefile.am
@@ -82,9 +82,13 @@ LIBGSTCHECK_EXPORTED_FUNCS = \
gst_check_setup_events \
gst_check_setup_events_with_stream_id \
gst_check_setup_sink_pad \
+ gst_check_setup_sink_pad_from_template \
gst_check_setup_sink_pad_by_name \
+ gst_check_setup_sink_pad_by_name_from_template \
gst_check_setup_src_pad \
+ gst_check_setup_src_pad_from_template \
gst_check_setup_src_pad_by_name \
+ gst_check_setup_src_pad_by_name_from_template \
gst_check_teardown_element \
gst_check_teardown_pad_by_name \
gst_check_teardown_sink_pad \
@@ -104,7 +108,11 @@ LIBGSTCHECK_EXPORTED_FUNCS = \
gst_test_clock_wait_for_next_pending_id \
gst_test_clock_wait_for_pending_id_count \
gst_test_clock_process_next_clock_id \
- gst_test_clock_get_next_entry_time
+ gst_test_clock_get_next_entry_time \
+ gst_test_clock_wait_for_multiple_pending_ids \
+ gst_test_clock_process_id_list \
+ gst_test_clock_id_list_get_latest_time
+
LIBGSTCHECK_EXPORTED_SYMBOLS = \
$(LIBGSTCHECK_EXPORTED_VARS) \
@@ -146,7 +154,7 @@ GstCheck-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstcheck-@GST_API_VE
--library-path=$(top_builddir)/gst \
--library=libgstcheck-@GST_API_VERSION@.la \
--include=Gst-@GST_API_VERSION@ \
- --libtool="$(top_builddir)/libtool" \
+ --libtool="${LIBTOOL}" \
--pkg gstreamer-@GST_API_VERSION@ \
--pkg-export gstreamer-check-@GST_API_VERSION@ \
--add-init-section="gst_init(NULL,NULL);" \
diff --git a/libs/gst/check/Makefile.in b/libs/gst/check/Makefile.in
index ce1bce9..9f470d4 100644
--- a/libs/gst/check/Makefile.in
+++ b/libs/gst/check/Makefile.in
@@ -92,7 +92,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/as-compiler-flag.m4 \
$(top_srcdir)/common/m4/as-docbook.m4 \
$(top_srcdir)/common/m4/as-libtool.m4 \
- $(top_srcdir)/common/m4/as-scrub-include.m4 \
$(top_srcdir)/common/m4/as-version.m4 \
$(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/common/m4/gst-arch.m4 \
@@ -634,9 +633,13 @@ LIBGSTCHECK_EXPORTED_FUNCS = \
gst_check_setup_events \
gst_check_setup_events_with_stream_id \
gst_check_setup_sink_pad \
+ gst_check_setup_sink_pad_from_template \
gst_check_setup_sink_pad_by_name \
+ gst_check_setup_sink_pad_by_name_from_template \
gst_check_setup_src_pad \
+ gst_check_setup_src_pad_from_template \
gst_check_setup_src_pad_by_name \
+ gst_check_setup_src_pad_by_name_from_template \
gst_check_teardown_element \
gst_check_teardown_pad_by_name \
gst_check_teardown_sink_pad \
@@ -656,7 +659,10 @@ LIBGSTCHECK_EXPORTED_FUNCS = \
gst_test_clock_wait_for_next_pending_id \
gst_test_clock_wait_for_pending_id_count \
gst_test_clock_process_next_clock_id \
- gst_test_clock_get_next_entry_time
+ gst_test_clock_get_next_entry_time \
+ gst_test_clock_wait_for_multiple_pending_ids \
+ gst_test_clock_process_id_list \
+ gst_test_clock_id_list_get_latest_time
LIBGSTCHECK_EXPORTED_SYMBOLS = \
$(LIBGSTCHECK_EXPORTED_VARS) \
@@ -1237,7 +1243,7 @@ $(SYMBOLS_FILE): $(libgstcheck_@GST_API_VERSION@include_HEADERS) libcheck/check.
@HAVE_INTROSPECTION_TRUE@ --library-path=$(top_builddir)/gst \
@HAVE_INTROSPECTION_TRUE@ --library=libgstcheck-@GST_API_VERSION@.la \
@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \
-@HAVE_INTROSPECTION_TRUE@ --libtool="$(top_builddir)/libtool" \
+@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \
@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --pkg-export gstreamer-check-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --add-init-section="gst_init(NULL,NULL);" \
diff --git a/libs/gst/check/gstcheck.c b/libs/gst/check/gstcheck.c
index 091a223..454ebb2 100644
--- a/libs/gst/check/gstcheck.c
+++ b/libs/gst/check/gstcheck.c
@@ -26,6 +26,10 @@
*
* These macros and functions are for internal use of the unit tests found
* inside the 'check' directories of various GStreamer packages.
+ *
+ * One notable feature is that one can use the environment variables GST_CHECK
+ * and GST_CHECK_IGNORE to select which tests to run or skip. Both variables
+ * can contain a comman separated list of test name globs (e.g. test_*).
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -259,10 +263,47 @@ GstPad *
gst_check_setup_src_pad_by_name (GstElement * element,
GstStaticPadTemplate * tmpl, const gchar * name)
{
+ GstPadTemplate *ptmpl = gst_static_pad_template_get (tmpl);
+ GstPad *srcpad;
+
+ srcpad =
+ gst_check_setup_src_pad_by_name_from_template (element, ptmpl, "sink");
+
+ gst_object_unref (ptmpl);
+
+ return srcpad;
+}
+
+/**
+ * gst_check_setup_src_pad_from_template:
+ * @element: element to setup pad on
+ * @tmpl: pad template
+ *
+ * Returns: (transfer full): a new pad
+ */
+GstPad *
+gst_check_setup_src_pad_from_template (GstElement * element,
+ GstPadTemplate * tmpl)
+{
+ return gst_check_setup_src_pad_by_name_from_template (element, tmpl, "sink");
+}
+
+/**
+ * gst_check_setup_src_pad_by_name_from_template:
+ * @element: element to setup pad on
+ * @tmpl: pad template
+ * @name: name
+ *
+ * Returns: (transfer full): a new pad
+ */
+GstPad *
+gst_check_setup_src_pad_by_name_from_template (GstElement * element,
+ GstPadTemplate * tmpl, const gchar * name)
+{
GstPad *srcpad, *sinkpad;
/* sending pad */
- srcpad = gst_pad_new_from_static_template (tmpl, "src");
+ srcpad = gst_pad_new_from_template (tmpl, "src");
GST_DEBUG_OBJECT (element, "setting up sending pad %p", srcpad);
fail_if (srcpad == NULL, "Could not create a srcpad");
ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
@@ -345,10 +386,47 @@ GstPad *
gst_check_setup_sink_pad_by_name (GstElement * element,
GstStaticPadTemplate * tmpl, const gchar * name)
{
+ GstPadTemplate *ptmpl = gst_static_pad_template_get (tmpl);
+ GstPad *sinkpad;
+
+ sinkpad =
+ gst_check_setup_sink_pad_by_name_from_template (element, ptmpl, "src");
+
+ gst_object_unref (ptmpl);
+
+ return sinkpad;
+}
+
+/**
+ * gst_check_setup_sink_pad_from_template:
+ * @element: element to setup pad on
+ * @tmpl: pad template
+ *
+ * Returns: (transfer full): a new pad
+ */
+GstPad *
+gst_check_setup_sink_pad_from_template (GstElement * element,
+ GstPadTemplate * tmpl)
+{
+ return gst_check_setup_sink_pad_by_name_from_template (element, tmpl, "src");
+}
+
+/**
+ * gst_check_setup_sink_pad_by_name_from_template:
+ * @element: element to setup pad on
+ * @tmpl: pad template
+ * @name: name
+ *
+ * Returns: (transfer full): a new pad
+ */
+GstPad *
+gst_check_setup_sink_pad_by_name_from_template (GstElement * element,
+ GstPadTemplate * tmpl, const gchar * name)
+{
GstPad *srcpad, *sinkpad;
/* receiving pad */
- sinkpad = gst_pad_new_from_static_template (tmpl, "sink");
+ sinkpad = gst_pad_new_from_template (tmpl, "sink");
GST_DEBUG_OBJECT (element, "setting up receiving pad %p", sinkpad);
fail_if (sinkpad == NULL, "Could not create a sinkpad");
@@ -460,7 +538,7 @@ buffer_event_function (GstPad * pad, GstObject * noparent, GstEvent * event)
* gst_check_element_push_buffer_list:
* @element_name: name of the element that needs to be created
* @buffer_in: (element-type GstBuffer) (transfer full): a list of buffers that needs to be
- * puched to the element
+ * pushed to the element
* @buffer_out: (element-type GstBuffer) (transfer full): a list of buffers that we expect from
* the element
* @last_flow_return: the last buffer push needs to give this GstFlowReturn
@@ -697,18 +775,26 @@ gst_check_run_suite (Suite * suite, const gchar * name, const gchar * fname)
return nf;
}
-gboolean
-_gst_check_run_test_func (const gchar * func_name)
+static gboolean
+gst_check_have_checks_list (const gchar * env_var_name)
+{
+ const gchar *env_val;
+
+ env_val = g_getenv (env_var_name);
+ return (env_val != NULL && *env_val != '\0');
+}
+
+static gboolean
+gst_check_func_is_in_list (const gchar * env_var, const gchar * func_name)
{
const gchar *gst_checks;
gboolean res = FALSE;
gchar **funcs, **f;
- gst_checks = g_getenv ("GST_CHECKS");
+ gst_checks = g_getenv (env_var);
- /* no filter specified => run all checks */
if (gst_checks == NULL || *gst_checks == '\0')
- return TRUE;
+ return FALSE;
/* only run specified functions */
funcs = g_strsplit (gst_checks, ",", -1);
@@ -722,6 +808,21 @@ _gst_check_run_test_func (const gchar * func_name)
return res;
}
+gboolean
+_gst_check_run_test_func (const gchar * func_name)
+{
+ /* if we have a whitelist, run it only if it's in the whitelist */
+ if (gst_check_have_checks_list ("GST_CHECKS"))
+ return gst_check_func_is_in_list ("GST_CHECKS", func_name);
+
+ /* if we have a blacklist, run it only if it's not in the blacklist */
+ if (gst_check_have_checks_list ("GST_CHECKS_IGNORE"))
+ return !gst_check_func_is_in_list ("GST_CHECKS_IGNORE", func_name);
+
+ /* no filter specified => run all checks */
+ return TRUE;
+}
+
/**
* gst_check_setup_events_with_stream_id:
* @srcpad: The src #GstPad to push on
@@ -730,7 +831,7 @@ _gst_check_run_test_func (const gchar * func_name)
* @format: The #GstFormat of the default segment to send
* @stream_id: A unique identifier for the stream
*
- * Push stream-start, caps and segment event, which concist of the minimum
+ * Push stream-start, caps and segment event, which consist of the minimum
* required events to allow streaming. Caps is optional to allow raw src
* testing.
*/
@@ -756,7 +857,7 @@ gst_check_setup_events_with_stream_id (GstPad * srcpad, GstElement * element,
* @caps: (allow-none): #GstCaps in case caps event must be sent
* @format: The #GstFormat of the default segment to send
*
- * Push stream-start, caps and segment event, which concist of the minimum
+ * Push stream-start, caps and segment event, which consist of the minimum
* required events to allow streaming. Caps is optional to allow raw src
* testing. If @element has more than one src or sink pad, use
* gst_check_setup_events_with_stream_id() instead.
diff --git a/libs/gst/check/gstcheck.h b/libs/gst/check/gstcheck.h
index 7b4b9d4..ee92579 100644
--- a/libs/gst/check/gstcheck.h
+++ b/libs/gst/check/gstcheck.h
@@ -73,10 +73,20 @@ GstElement *gst_check_setup_element (const gchar * factory);
void gst_check_teardown_element (GstElement * element);
GstPad *gst_check_setup_src_pad (GstElement * element,
GstStaticPadTemplate * tmpl);
+GstPad *gst_check_setup_src_pad_from_template (GstElement * element,
+ GstPadTemplate * tmpl);
GstPad * gst_check_setup_src_pad_by_name (GstElement * element,
GstStaticPadTemplate * tmpl, const gchar *name);
+GstPad * gst_check_setup_src_pad_by_name_from_template (GstElement * element,
+ GstPadTemplate * tmpl, const gchar *name);
+GstPad *gst_check_setup_sink_pad (GstElement * element,
+ GstStaticPadTemplate * tmpl);
+GstPad *gst_check_setup_sink_pad_from_template (GstElement * element,
+ GstPadTemplate * tmpl);
GstPad * gst_check_setup_sink_pad_by_name (GstElement * element,
GstStaticPadTemplate * tmpl, const gchar *name);
+GstPad * gst_check_setup_sink_pad_by_name_from_template (GstElement * element,
+ GstPadTemplate * tmpl, const gchar *name);
void gst_check_teardown_pad_by_name (GstElement * element, const gchar *name);
void gst_check_teardown_src_pad (GstElement * element);
void gst_check_drop_buffers (void);
@@ -88,8 +98,6 @@ void gst_check_element_push_buffer_list (const gchar * element_name,
void gst_check_element_push_buffer (const gchar * element_name,
GstBuffer * buffer_in, GstCaps * caps_in, GstBuffer * buffer_out,
GstCaps *caps_out);
-GstPad *gst_check_setup_sink_pad (GstElement * element,
- GstStaticPadTemplate * tmpl);
void gst_check_teardown_sink_pad (GstElement * element);
void gst_check_abi_list (GstCheckABIStruct list[], gboolean have_abi_sizes);
gint gst_check_run_suite (Suite * suite, const gchar * name,
@@ -558,7 +566,8 @@ int main (int argc, char **argv) \
}
/* Hack to allow run-time selection of unit tests to run via the
- * GST_CHECKS environment variable (test function names, comma-separated) */
+ * GST_CHECKS environment variable (test function names globs, comma
+ * separated), or GST_CHECKS_IGNORE with the same semantics */
gboolean _gst_check_run_test_func (const gchar * func_name);
@@ -573,12 +582,13 @@ __gst_tcase_add_test (TCase * tc, TFun tf, const char * fname, int signal,
#define _tcase_add_test __gst_tcase_add_test
-/* add define to skip broken tests */
+/* A special variant to add broken tests. These are normally skipped, but can be
+ * forced to run via GST_CHECKS */
#define tcase_skip_broken_test(chain,test_func) \
G_STMT_START { \
const char *env = g_getenv ("GST_CHECKS"); \
\
- if (env != NULL && strstr (env, G_STRINGIFY (test_func))) { \
+ if (env != NULL && g_pattern_match_simple (env, G_STRINGIFY (test_func))) { \
tcase_add_test(chain,test_func); \
} else { \
g_printerr ("FIXME: skipping test %s because it's broken\n", G_STRINGIFY (test_func)); \
diff --git a/libs/gst/check/gsttestclock.c b/libs/gst/check/gsttestclock.c
index f9737a6..a609766 100644
--- a/libs/gst/check/gsttestclock.c
+++ b/libs/gst/check/gsttestclock.c
@@ -2,6 +2,8 @@
*
* Copyright (C) 2008 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
* Copyright (C) 2012 Sebastian Rasmussen <sebastian.rasmussen@axis.com>
+ * Copyright (C) 2012 Havard Graff <havard@pexip.com>
+ * Copyright (C) 2013 Haakon Sporsheim <haakon@pexip.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -57,12 +59,12 @@
* #GstClock allows for setting up single shot or periodic clock notifications
* as well as waiting for these notifications synchronously (using
* gst_clock_id_wait()) or asynchronously (using gst_clock_id_wait_async() or
- * gst_clock_id_wait_async_full()). This is used by many GStreamer elements,
+ * gst_clock_id_wait_async()). This is used by many GStreamer elements,
* among them #GstBaseSrc and #GstBaseSink.
*
* #GstTestClock keeps track of these clock notifications. By calling
* gst_test_clock_wait_for_next_pending_id() or
- * gst_test_clock_wait_for_pending_id_count() a unit tests may wait for the
+ * gst_test_clock_wait_for_multiple_pending_ids() a unit tests may wait for the
* next one or several clock notifications to be requested. Additionally unit
* tests may release blocked waits in a controlled fashion by calling
* gst_test_clock_process_next_clock_id(). This way a unit test can control the
@@ -76,12 +78,12 @@
*
* N.B.: When a unit test waits for a certain amount of clock notifications to
* be requested in gst_test_clock_wait_for_next_pending_id() or
- * gst_test_clock_wait_for_pending_id_count() then these functions may block
+ * gst_test_clock_wait_for_multiple_pending_ids() then these functions may block
* for a long time. If they block forever then the expected clock notifications
* were never requested from #GstTestClock, and so the assumptions in the code
- * of the unit test are wrong. The unit test case runner in #GstCheck is
+ * of the unit test are wrong. The unit test case runner in gstcheck is
* expected to catch these cases either by the default test case timeout or the
- * one set for the unit test by calling tcase_set_timeout().
+ * one set for the unit test by calling tcase_set_timeout\(\).
*
* The sample code below assumes that the element under test will delay a
* buffer pushed on the source pad by some latency until it arrives on the sink
@@ -388,6 +390,7 @@ gst_test_clock_set_property (GObject * object, guint property_id,
static GstClockTime
gst_test_clock_get_resolution (GstClock * clock)
{
+ (void) clock;
return 1;
}
@@ -592,6 +595,51 @@ gst_clock_entry_context_compare_func (gconstpointer a, gconstpointer b)
return gst_clock_id_compare_func (ctx_a->clock_entry, ctx_b->clock_entry);
}
+static void
+process_entry_context_unlocked (GstTestClock * test_clock,
+ GstClockEntryContext * ctx)
+{
+ GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
+ GstClockEntry *entry = ctx->clock_entry;
+
+ if (ctx->time_diff >= 0)
+ GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_OK;
+ else
+ GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_EARLY;
+
+ if (entry->func != NULL) {
+ GST_OBJECT_UNLOCK (test_clock);
+ entry->func (GST_CLOCK (test_clock), priv->internal_time, entry,
+ entry->user_data);
+ GST_OBJECT_LOCK (test_clock);
+ }
+
+ gst_test_clock_remove_entry (test_clock, entry);
+
+ if (GST_CLOCK_ENTRY_TYPE (entry) == GST_CLOCK_ENTRY_PERIODIC) {
+ GST_CLOCK_ENTRY_TIME (entry) += GST_CLOCK_ENTRY_INTERVAL (entry);
+
+ if (entry->func != NULL)
+ gst_test_clock_add_entry (test_clock, entry, NULL);
+ }
+}
+
+static GList *
+gst_test_clock_get_pending_id_list_unlocked (GstTestClock * test_clock)
+{
+ GstTestClockPrivate *priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
+ GQueue queue = G_QUEUE_INIT;
+ GList *cur;
+
+ for (cur = priv->entry_contexts; cur != NULL; cur = cur->next) {
+ GstClockEntryContext *ctx = cur->data;
+
+ g_queue_push_tail (&queue, gst_clock_id_ref (ctx->clock_entry));
+ }
+
+ return queue.head;
+}
+
/**
* gst_test_clock_new:
*
@@ -832,31 +880,26 @@ gst_test_clock_wait_for_next_pending_id (GstTestClock * test_clock,
* @test_clock. There is no timeout for this wait, see the main description of
* #GstTestClock.
*
- * MT safe.
- *
* Since: 1.2
+ *
+ * Deprecated: use gst_test_clock_wait_for_multiple_pending_ids() instead.
*/
+#ifndef GST_REMOVE_DEPRECATED
+#ifdef GST_DISABLE_DEPRECATED
+void gst_test_clock_wait_for_pending_id_count (GstTestClock * test_clock,
+ guint count);
+#endif
void
gst_test_clock_wait_for_pending_id_count (GstTestClock * test_clock,
guint count)
{
- GstTestClockPrivate *priv;
-
- g_return_if_fail (GST_IS_TEST_CLOCK (test_clock));
-
- priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
-
- GST_OBJECT_LOCK (test_clock);
-
- while (gst_test_clock_peek_id_count_unlocked (test_clock) < count)
- g_cond_wait (&priv->entry_added_cond, GST_OBJECT_GET_LOCK (test_clock));
-
- GST_OBJECT_UNLOCK (test_clock);
+ gst_test_clock_wait_for_multiple_pending_ids (test_clock, count, NULL);
}
+#endif
/**
* gst_test_clock_process_next_clock_id:
- * @test_clock: a #GstTestClock for which to retrive the next pending clock
+ * @test_clock: a #GstTestClock for which to retrieve the next pending clock
* notification
*
* MT safe.
@@ -888,30 +931,8 @@ gst_test_clock_process_next_clock_id (GstTestClock * test_clock)
result = gst_clock_id_ref (ctx->clock_entry);
}
- if (result != NULL) {
- GstClockEntry *entry = ctx->clock_entry;
-
- if (ctx->time_diff >= 0)
- GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_OK;
- else
- GST_CLOCK_ENTRY_STATUS (entry) = GST_CLOCK_EARLY;
-
- if (entry->func != NULL) {
- GST_OBJECT_UNLOCK (test_clock);
- entry->func (GST_CLOCK (test_clock), priv->internal_time, entry,
- entry->user_data);
- GST_OBJECT_LOCK (test_clock);
- }
-
- gst_test_clock_remove_entry (test_clock, entry);
-
- if (GST_CLOCK_ENTRY_TYPE (entry) == GST_CLOCK_ENTRY_PERIODIC) {
- GST_CLOCK_ENTRY_TIME (entry) += GST_CLOCK_ENTRY_INTERVAL (entry);
-
- if (entry->func != NULL)
- gst_test_clock_add_entry (test_clock, entry, NULL);
- }
- }
+ if (result != NULL)
+ process_entry_context_unlocked (test_clock, ctx);
GST_OBJECT_UNLOCK (test_clock);
@@ -957,3 +978,103 @@ gst_test_clock_get_next_entry_time (GstTestClock * test_clock)
return result;
}
+
+/**
+ * gst_test_clock_wait_for_multiple_pending_ids:
+ * @test_clock: #GstTestClock for which to await having enough pending clock
+ * @count: the number of pending clock notifications to wait for
+ * @pending_list: (out) (element-type Gst.ClockID) (transfer full) (allow-none): Address
+ * of a #GList pointer variable to store the list of pending #GstClockIDs
+ * that expired, or NULL
+ *
+ * Blocks until at least @count clock notifications have been requested from
+ * @test_clock. There is no timeout for this wait, see the main description of
+ * #GstTestClock.
+ *
+ * MT safe.
+ *
+ * Since: 1.4
+ */
+void
+gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock,
+ guint count, GList ** pending_list)
+{
+ GstTestClockPrivate *priv;
+
+ g_return_if_fail (GST_IS_TEST_CLOCK (test_clock));
+ priv = GST_TEST_CLOCK_GET_PRIVATE (test_clock);
+
+ GST_OBJECT_LOCK (test_clock);
+
+ while (g_list_length (priv->entry_contexts) < count)
+ g_cond_wait (&priv->entry_added_cond, GST_OBJECT_GET_LOCK (test_clock));
+
+ if (pending_list)
+ *pending_list = gst_test_clock_get_pending_id_list_unlocked (test_clock);
+
+ GST_OBJECT_UNLOCK (test_clock);
+}
+
+/**
+ * gst_test_clock_process_id_list:
+ * @test_clock: #GstTestClock for which to process the pending IDs
+ * @pending_list: (element-type Gst.ClockID) (transfer none) (allow-none): List
+ * of pending #GstClockIDs
+ *
+ * Processes and releases the pending IDs in the list.
+ *
+ * MT safe.
+ *
+ * Since: 1.4
+ */
+guint
+gst_test_clock_process_id_list (GstTestClock * test_clock,
+ const GList * pending_list)
+{
+ const GList *cur;
+ guint result = 0;
+
+ g_return_val_if_fail (GST_IS_TEST_CLOCK (test_clock), 0);
+
+ GST_OBJECT_LOCK (test_clock);
+
+ for (cur = pending_list; cur != NULL; cur = cur->next) {
+ GstClockID pending_id = cur->data;
+ GstClockEntryContext *ctx =
+ gst_test_clock_lookup_entry_context (test_clock, pending_id);
+ if (ctx) {
+ process_entry_context_unlocked (test_clock, ctx);
+ result++;
+ }
+ }
+ GST_OBJECT_UNLOCK (test_clock);
+
+ return result;
+}
+
+/**
+ * gst_test_clock_id_list_get_latest_time:
+ * @pending_list: (element-type Gst.ClockID) (transfer none) (allow-none): List
+ * of of pending #GstClockIDs
+ *
+ * Finds the latest time inside the list.
+ *
+ * MT safe.
+ *
+ * Since: 1.4
+ */
+GstClockTime
+gst_test_clock_id_list_get_latest_time (const GList * pending_list)
+{
+ const GList *cur;
+ GstClockTime result = 0;
+
+ for (cur = pending_list; cur != NULL; cur = cur->next) {
+ GstClockID *pending_id = cur->data;
+ GstClockTime time = gst_clock_id_get_time (pending_id);
+ if (time > result)
+ result = time;
+ }
+
+ return result;
+}
diff --git a/libs/gst/check/gsttestclock.h b/libs/gst/check/gsttestclock.h
index 699e169..af7a5f1 100644
--- a/libs/gst/check/gsttestclock.h
+++ b/libs/gst/check/gsttestclock.h
@@ -2,6 +2,8 @@
*
* Copyright (C) 2008 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com>
* Copyright (C) 2012 Sebastian Rasmussen <sebastian.rasmussen@axis.com>
+ * Copyright (C) 2012 Havard Graff <havard@pexip.com>
+ * Copyright (C) 2013 Haakon Sporsheim <haakon@pexip.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -78,11 +80,11 @@ GstClock * gst_test_clock_new (void);
GstClock * gst_test_clock_new_with_start_time (GstClockTime start_time);
-void gst_test_clock_set_time (GstTestClock * test_clock,
- GstClockTime new_time);
+void gst_test_clock_set_time (GstTestClock * test_clock,
+ GstClockTime new_time);
-void gst_test_clock_advance_time (GstTestClock * test_clock,
- GstClockTimeDiff delta);
+void gst_test_clock_advance_time (GstTestClock * test_clock,
+ GstClockTimeDiff delta);
guint gst_test_clock_peek_id_count (GstTestClock * test_clock);
@@ -91,16 +93,27 @@ gboolean gst_test_clock_has_id (GstTestClock * test_clock, GstClockID id);
gboolean gst_test_clock_peek_next_pending_id (GstTestClock * test_clock,
GstClockID * pending_id);
-void gst_test_clock_wait_for_next_pending_id (GstTestClock * test_clock,
- GstClockID * pending_id);
+void gst_test_clock_wait_for_next_pending_id (GstTestClock * test_clock,
+ GstClockID * pending_id);
+#ifndef GST_DISABLE_DEPRECATED
void gst_test_clock_wait_for_pending_id_count (GstTestClock * test_clock,
guint count);
+#endif
GstClockID gst_test_clock_process_next_clock_id (GstTestClock * test_clock);
GstClockTime gst_test_clock_get_next_entry_time (GstTestClock * test_clock);
+void gst_test_clock_wait_for_multiple_pending_ids (GstTestClock * test_clock,
+ guint count,
+ GList ** pending_list);
+
+guint gst_test_clock_process_id_list (GstTestClock * test_clock,
+ const GList * pending_list);
+
+GstClockTime gst_test_clock_id_list_get_latest_time (const GList * pending_list);
+
G_END_DECLS
#endif /* __GST_TEST_CLOCK_H__ */
diff --git a/libs/gst/check/libcheck/Makefile.in b/libs/gst/check/libcheck/Makefile.in
index ad69bac..1d3988f 100644
--- a/libs/gst/check/libcheck/Makefile.in
+++ b/libs/gst/check/libcheck/Makefile.in
@@ -89,7 +89,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/as-compiler-flag.m4 \
$(top_srcdir)/common/m4/as-docbook.m4 \
$(top_srcdir)/common/m4/as-libtool.m4 \
- $(top_srcdir)/common/m4/as-scrub-include.m4 \
$(top_srcdir)/common/m4/as-version.m4 \
$(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/common/m4/gst-arch.m4 \
diff --git a/libs/gst/check/libcheck/check.c b/libs/gst/check/libcheck/check.c
index 9aba434..2b7f481 100644
--- a/libs/gst/check/libcheck/check.c
+++ b/libs/gst/check/libcheck/check.c
@@ -248,7 +248,7 @@ _fail_unless (int result, const char *file, int line, const char *expr, ...)
send_failure_info (buf);
if (cur_fork_status () == CK_FORK) {
#ifdef _POSIX_VERSION
- exit (1);
+ _exit (1);
#endif /* _POSIX_VERSION */
}
}
diff --git a/libs/gst/controller/Makefile.am b/libs/gst/controller/Makefile.am
index 3ae4098..4050f27 100644
--- a/libs/gst/controller/Makefile.am
+++ b/libs/gst/controller/Makefile.am
@@ -63,7 +63,7 @@ GstController-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstcontroller-@
--library-path=$(top_builddir)/gst \
--library=libgstcontroller-@GST_API_VERSION@.la \
--include=Gst-@GST_API_VERSION@ \
- --libtool="$(top_builddir)/libtool" \
+ --libtool="${LIBTOOL}" \
--pkg gstreamer-@GST_API_VERSION@ \
--pkg-export gstreamer-controller-@GST_API_VERSION@ \
--add-init-section="gst_init(NULL,NULL);" \
diff --git a/libs/gst/controller/Makefile.in b/libs/gst/controller/Makefile.in
index 3badfc6..8a02328 100644
--- a/libs/gst/controller/Makefile.in
+++ b/libs/gst/controller/Makefile.in
@@ -92,7 +92,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/as-compiler-flag.m4 \
$(top_srcdir)/common/m4/as-docbook.m4 \
$(top_srcdir)/common/m4/as-libtool.m4 \
- $(top_srcdir)/common/m4/as-scrub-include.m4 \
$(top_srcdir)/common/m4/as-version.m4 \
$(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/common/m4/gst-arch.m4 \
@@ -958,7 +957,7 @@ Android.mk: Makefile.am
@HAVE_INTROSPECTION_TRUE@ --library-path=$(top_builddir)/gst \
@HAVE_INTROSPECTION_TRUE@ --library=libgstcontroller-@GST_API_VERSION@.la \
@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \
-@HAVE_INTROSPECTION_TRUE@ --libtool="$(top_builddir)/libtool" \
+@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \
@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --pkg-export gstreamer-controller-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --add-init-section="gst_init(NULL,NULL);" \
diff --git a/libs/gst/controller/gstinterpolationcontrolsource.c b/libs/gst/controller/gstinterpolationcontrolsource.c
index 0aea6cd..b8a3c22 100644
--- a/libs/gst/controller/gstinterpolationcontrolsource.c
+++ b/libs/gst/controller/gstinterpolationcontrolsource.c
@@ -524,7 +524,7 @@ static gboolean
{
GstControlSource *csource = GST_CONTROL_SOURCE (self);
- if (mode >= num_interpolation_modes && (int) mode < 0) {
+ if (mode >= num_interpolation_modes || (int) mode < 0) {
GST_WARNING ("interpolation mode %d invalid or not implemented yet", mode);
return FALSE;
}
diff --git a/libs/gst/controller/gsttimedvaluecontrolsource.c b/libs/gst/controller/gsttimedvaluecontrolsource.c
index 19cb927..0d0b8be 100644
--- a/libs/gst/controller/gsttimedvaluecontrolsource.c
+++ b/libs/gst/controller/gsttimedvaluecontrolsource.c
@@ -26,7 +26,7 @@
* SECTION:gsttimedvaluecontrolsource
* @short_description: timed value control source base class
*
- * Base class for #GstContrlSources that use time-stamped values.
+ * Base class for #GstControlSource that use time-stamped values.
*
* When overriding bind, chain up first to give this bind implementation a
* chance to setup things.
diff --git a/libs/gst/helpers/Makefile.in b/libs/gst/helpers/Makefile.in
index 6e640f6..67cb892 100644
--- a/libs/gst/helpers/Makefile.in
+++ b/libs/gst/helpers/Makefile.in
@@ -89,7 +89,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/as-compiler-flag.m4 \
$(top_srcdir)/common/m4/as-docbook.m4 \
$(top_srcdir)/common/m4/as-libtool.m4 \
- $(top_srcdir)/common/m4/as-scrub-include.m4 \
$(top_srcdir)/common/m4/as-version.m4 \
$(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/common/m4/gst-arch.m4 \
diff --git a/libs/gst/net/Makefile.am b/libs/gst/net/Makefile.am
index dbd342b..f022b92 100644
--- a/libs/gst/net/Makefile.am
+++ b/libs/gst/net/Makefile.am
@@ -63,7 +63,7 @@ GstNet-@GST_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libgstnet-@GST_API_VERSIO
--library=libgstnet-@GST_API_VERSION@.la \
--include=Gst-@GST_API_VERSION@ \
--include=Gio-2.0 \
- --libtool="$(top_builddir)/libtool" \
+ --libtool="${LIBTOOL}" \
--pkg gstreamer-@GST_API_VERSION@ \
--pkg gio-2.0 \
--pkg-export="gstreamer-net-@GST_API_VERSION@" \
diff --git a/libs/gst/net/Makefile.in b/libs/gst/net/Makefile.in
index 2ec6f6e..abc967e 100644
--- a/libs/gst/net/Makefile.in
+++ b/libs/gst/net/Makefile.in
@@ -92,7 +92,6 @@ am__aclocal_m4_deps = $(top_srcdir)/common/m4/as-ac-expand.m4 \
$(top_srcdir)/common/m4/as-compiler-flag.m4 \
$(top_srcdir)/common/m4/as-docbook.m4 \
$(top_srcdir)/common/m4/as-libtool.m4 \
- $(top_srcdir)/common/m4/as-scrub-include.m4 \
$(top_srcdir)/common/m4/as-version.m4 \
$(top_srcdir)/common/m4/ax_create_stdint_h.m4 \
$(top_srcdir)/common/m4/gst-arch.m4 \
@@ -939,7 +938,7 @@ Android.mk: Makefile.am
@HAVE_INTROSPECTION_TRUE@ --library=libgstnet-@GST_API_VERSION@.la \
@HAVE_INTROSPECTION_TRUE@ --include=Gst-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --include=Gio-2.0 \
-@HAVE_INTROSPECTION_TRUE@ --libtool="$(top_builddir)/libtool" \
+@HAVE_INTROSPECTION_TRUE@ --libtool="${LIBTOOL}" \
@HAVE_INTROSPECTION_TRUE@ --pkg gstreamer-@GST_API_VERSION@ \
@HAVE_INTROSPECTION_TRUE@ --pkg gio-2.0 \
@HAVE_INTROSPECTION_TRUE@ --pkg-export="gstreamer-net-@GST_API_VERSION@" \
diff --git a/libs/gst/net/gstnetaddressmeta.c b/libs/gst/net/gstnetaddressmeta.c
index 118a685..164ce4f 100644
--- a/libs/gst/net/gstnetaddressmeta.c
+++ b/libs/gst/net/gstnetaddressmeta.c
@@ -24,8 +24,6 @@
* #GstNetAddress can be used to store a network address. #GstNetAddressMeta can
* be used to store a network address in a #GstBuffer so that it network
* elements can track the to and from address of the buffer.
- *
- * Last reviewed on 2011-11-03 (0.11.2)
*/
#include <string.h>
diff --git a/libs/gst/net/gstnetclientclock.c b/libs/gst/net/gstnetclientclock.c
index 7d9843f..dd1dafe 100644
--- a/libs/gst/net/gstnetclientclock.c
+++ b/libs/gst/net/gstnetclientclock.c
@@ -38,13 +38,13 @@
* This clock will poll the time provider and will update its calibration
* parameters based on the local and remote observations.
*
+ * The "round-trip" property limits the maximum round trip packets can take.
+ *
* Various parameters of the clock can be configured with the parent #GstClock
* "timeout", "window-size" and "window-threshold" object properties.
*
* A #GstNetClientClock is typically set on a #GstPipeline with
* gst_pipeline_use_clock().
- *
- * Last reviewed on 2005-11-23 (0.9.5)
*/
#ifdef HAVE_CONFIG_H
@@ -62,12 +62,14 @@ GST_DEBUG_CATEGORY_STATIC (ncc_debug);
#define DEFAULT_ADDRESS "127.0.0.1"
#define DEFAULT_PORT 5637
#define DEFAULT_TIMEOUT GST_SECOND
+#define DEFAULT_ROUNDTRIP_LIMIT GST_SECOND
enum
{
PROP_0,
PROP_ADDRESS,
- PROP_PORT
+ PROP_PORT,
+ PROP_ROUNDTRIP_LIMIT
};
#define GST_NET_CLIENT_CLOCK_GET_PRIVATE(obj) \
@@ -82,6 +84,8 @@ struct _GstNetClientClockPrivate
GCancellable *cancel;
GstClockTime timeout_expiration;
+ GstClockTime roundtrip_limit;
+ GstClockTime rtt_avg;
gchar *address;
gint port;
@@ -122,6 +126,26 @@ gst_net_client_clock_class_init (GstNetClientClockClass * klass)
g_param_spec_int ("port", "port",
"The port on which the remote server is listening", 0, G_MAXUINT16,
DEFAULT_PORT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /**
+ * GstNetClientClock::round-trip-limit:
+ *
+ * Maximum allowed round-trip for packets. If this property is set to a nonzero
+ * value, all packets with a round-trip interval larger than this limit will be
+ * ignored. This is useful for networks with severe and fluctuating transport
+ * delays. Filtering out these packets increases stability of the synchronization.
+ * On the other hand, the lower the limit, the higher the amount of filtered
+ * packets. Empirical tests are typically necessary to estimate a good value
+ * for the limit.
+ * If the property is set to zero, the limit is disabled.
+ *
+ * Since: 1.4
+ */
+ g_object_class_install_property (gobject_class, PROP_ROUNDTRIP_LIMIT,
+ g_param_spec_uint64 ("round-trip-limit", "round-trip limit",
+ "Maximum tolerable round-trip interval for packets, in nanoseconds "
+ "(0 = no limit)", 0, G_MAXUINT64, DEFAULT_ROUNDTRIP_LIMIT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
@@ -140,6 +164,8 @@ gst_net_client_clock_init (GstNetClientClock * self)
priv->thread = NULL;
priv->servaddr = NULL;
+ priv->rtt_avg = GST_CLOCK_TIME_NONE;
+ priv->roundtrip_limit = DEFAULT_ROUNDTRIP_LIMIT;
}
static void
@@ -184,6 +210,9 @@ gst_net_client_clock_set_property (GObject * object, guint prop_id,
case PROP_PORT:
self->priv->port = g_value_get_int (value);
break;
+ case PROP_ROUNDTRIP_LIMIT:
+ self->priv->roundtrip_limit = g_value_get_uint64 (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -203,6 +232,9 @@ gst_net_client_clock_get_property (GObject * object, guint prop_id,
case PROP_PORT:
g_value_set_int (value, self->priv->port);
break;
+ case PROP_ROUNDTRIP_LIMIT:
+ g_value_set_uint64 (value, self->priv->roundtrip_limit);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -213,21 +245,58 @@ static void
gst_net_client_clock_observe_times (GstNetClientClock * self,
GstClockTime local_1, GstClockTime remote, GstClockTime local_2)
{
+ GstNetClientClockPrivate *priv = self->priv;
GstClockTime current_timeout;
GstClockTime local_avg;
gdouble r_squared;
GstClock *clock;
+ GstClockTime rtt;
- if (local_2 < local_1)
+ if (local_2 < local_1) {
+ GST_LOG_OBJECT (self, "Dropping observation: receive time %" GST_TIME_FORMAT
+ " < send time %" GST_TIME_FORMAT, GST_TIME_ARGS (local_1),
+ GST_TIME_ARGS (local_2));
goto bogus_observation;
+ }
+
+ rtt = GST_CLOCK_DIFF (local_1, local_2);
+
+ if ((self->priv->roundtrip_limit > 0) && (rtt > self->priv->roundtrip_limit)) {
+ GST_LOG_OBJECT (self,
+ "Dropping observation: RTT %" GST_TIME_FORMAT " > limit %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (rtt),
+ GST_TIME_ARGS (self->priv->roundtrip_limit));
+ goto bogus_observation;
+ }
+
+ /* Track an average round trip time, for a bit of smoothing */
+ /* Always update before discarding a sample, so genuine changes in
+ * the network get picked up, eventually */
+ if (priv->rtt_avg == GST_CLOCK_TIME_NONE)
+ priv->rtt_avg = rtt;
+ else if (rtt < priv->rtt_avg) /* Shorter RTTs carry more weight than longer */
+ priv->rtt_avg = (3 * priv->rtt_avg + rtt) / 4;
+ else
+ priv->rtt_avg = (7 * priv->rtt_avg + rtt) / 8;
+
+ if (rtt > 2 * priv->rtt_avg) {
+ GST_LOG_OBJECT (self,
+ "Dropping observation, long RTT %" GST_TIME_FORMAT " > 2 * avg %"
+ GST_TIME_FORMAT, GST_TIME_ARGS (rtt), GST_TIME_ARGS (priv->rtt_avg));
+ goto bogus_observation;
+ }
local_avg = (local_2 + local_1) / 2;
+ GST_LOG_OBJECT (self, "local1 %" G_GUINT64_FORMAT " remote %" G_GUINT64_FORMAT
+ " localavg %" G_GUINT64_FORMAT " local2 %" G_GUINT64_FORMAT,
+ local_1, remote, local_avg, local_2);
+
clock = GST_CLOCK_CAST (self);
if (gst_clock_add_observation (GST_CLOCK (self), local_avg, remote,
&r_squared)) {
- /* geto formula */
+ /* ghetto formula - shorter timeout for bad correlations */
current_timeout = (1e-3 / (1 - MIN (r_squared, 0.99999))) * GST_SECOND;
current_timeout = MIN (current_timeout, gst_clock_get_timeout (clock));
} else {
@@ -240,12 +309,9 @@ gst_net_client_clock_observe_times (GstNetClientClock * self,
return;
bogus_observation:
- {
- GST_WARNING_OBJECT (self, "time packet receive time < send time (%"
- GST_TIME_FORMAT " < %" GST_TIME_FORMAT ")", GST_TIME_ARGS (local_1),
- GST_TIME_ARGS (local_2));
- return;
- }
+ /* Schedule a new packet again soon */
+ self->priv->timeout_expiration = gst_util_get_timestamp () + (GST_SECOND / 4);
+ return;
}
static gpointer
@@ -487,7 +553,7 @@ gst_net_client_clock_stop (GstNetClientClock * self)
* clock.
*/
GstClock *
-gst_net_client_clock_new (gchar * name, const gchar * remote_address,
+gst_net_client_clock_new (const gchar * name, const gchar * remote_address,
gint remote_port, GstClockTime base_time)
{
/* FIXME: gst_net_client_clock_new() should be a thin wrapper for g_object_new() */
diff --git a/libs/gst/net/gstnetclientclock.h b/libs/gst/net/gstnetclientclock.h
index 8e59807..b7243f1 100644
--- a/libs/gst/net/gstnetclientclock.h
+++ b/libs/gst/net/gstnetclientclock.h
@@ -70,7 +70,7 @@ struct _GstNetClientClockClass {
GType gst_net_client_clock_get_type (void);
-GstClock* gst_net_client_clock_new (gchar *name, const gchar *remote_address,
+GstClock* gst_net_client_clock_new (const gchar *name, const gchar *remote_address,
gint remote_port, GstClockTime base_time);
G_END_DECLS
diff --git a/libs/gst/net/gstnettimepacket.c b/libs/gst/net/gstnettimepacket.c
index f6b3bef..7541995 100644
--- a/libs/gst/net/gstnettimepacket.c
+++ b/libs/gst/net/gstnettimepacket.c
@@ -26,8 +26,6 @@
*
* Various functions for receiving, sending an serializing #GstNetTimePacket
* structures.
- *
- * Last reviewed on 2005-11-23 (0.9.5)
*/
#ifdef HAVE_CONFIG_H
@@ -210,7 +208,7 @@ short_packet:
*
* MT safe.
*
- * Returns: TRUE if successful, FALSE in case an error occured.
+ * Returns: TRUE if successful, FALSE in case an error occurred.
*/
gboolean
gst_net_time_packet_send (const GstNetTimePacket * packet,
diff --git a/libs/gst/net/gstnettimeprovider.c b/libs/gst/net/gstnettimeprovider.c
index 202b6c7..8e030d7 100644
--- a/libs/gst/net/gstnettimeprovider.c
+++ b/libs/gst/net/gstnettimeprovider.c
@@ -31,8 +31,6 @@
* query the exposed clock over the network for its values.
*
* The #GstNetTimeProvider typically wraps the clock used by a #GstPipeline.
- *
- * Last reviewed on 2005-11-23 (0.9.5)
*/
#ifdef HAVE_CONFIG_H
@@ -209,8 +207,7 @@ gst_net_time_provider_thread (gpointer data)
}
}
- if (err != NULL)
- g_error_free (err);
+ g_error_free (err);
GST_INFO_OBJECT (self, "time provider thread is stopping");
return NULL;
@@ -325,7 +322,8 @@ gst_net_time_provider_start (GstNetTimeProvider * self)
GST_DEBUG_OBJECT (self, "notifying port %d", port);
g_object_notify (G_OBJECT (self), "port");
}
- GST_DEBUG_OBJECT (self, "bound on UDP address %s, port %d", address, port);
+ GST_DEBUG_OBJECT (self, "bound on UDP address %s, port %d",
+ self->priv->address, port);
g_object_unref (bound_addr);
self->priv->socket = socket;