diff --git a/autogen.sh b/autogen.sh
index 42a3281be4..8a4d60b2c2 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -191,10 +191,14 @@ automake --add-missing || {
# now remove the cache, because it can be considered dangerous in this case
rm -f config.cache
-# The new configure options for busy application developers (Hadess)
-#./configure --enable-maintainer-mode --enable-debug --enable-DEBUG "$@" || {
+CONFIGURE_OPT='--enable-maintainer-mode --enable-plugin-builddir --enable-debug --enable-DEBUG'
-./configure --enable-maintainer-mode --enable-plugin-builddir --enable-debug --enable-DEBUG "$@" || {
+echo
+echo "./configure default flags: $CONFIGURE_OPT"
+echo "using: $CONFIGURE_OPT $@"
+echo
+
+./configure $CONFIGURE_OPT "$@" || {
echo
echo "configure failed"
exit 1
diff --git a/configure.base b/configure.base
index de9b8151ac..7597efb68b 100644
--- a/configure.base
+++ b/configure.base
@@ -216,13 +216,6 @@ GST_CHECK_FEATURE(GLIB2, [use of glib-2.0 and GObject], , [
])
AC_SUBST(USE_GLIB2)
-dnl FIXME: check for gtk2 and gnome2 - these conditionals are currently
-dnl always false.
-AM_CONDITIONAL(USE_GTK2, test "x$USE_GTK2" = "xyes")
-AC_SUBST(USE_GTK2)
-AM_CONDITIONAL(USE_GNOME2, test "x$USE_GNOME2" = "xyes")
-AC_SUBST(USE_GNOME2)
-
if test x$USE_GLIB2 = xno; then
dnl Check for glib and gtk
AM_PATH_GLIB(1.2.0,,
@@ -230,11 +223,24 @@ if test x$USE_GLIB2 = xno; then
glib gmodule gthread)
AM_PATH_GTK(1.2.0,,
AC_MSG_ERROR(Cannot find gtk: Is gtk-config in path?))
+ HAVE_GTK=yes
CORE_LIBS="$CORE_LIBS $GLIB_LIBS $GTK_LIBS"
CORE_CFLAGS="$CORE_CFLAGS $GLIB_CFLAGS $GTK_CFLAGS"
+else
+ PKG_CHECK_MODULES(GTK2, gtk+-2.0, HAVE_GTK=yes, HAVE_GTK=no)
+
+ GTK_FLAGS=$GTK2_CFLAGS
+ GTK_LIBS=$GTK2_LIBS
+
+ dnl FIXME: check for gnome2 - this conditional is currently
+ dnl always false.
+ AM_CONDITIONAL(USE_GNOME2, test "x$USE_GNOME2" = "xyes")
+ AC_SUBST(USE_GNOME2)
fi
+AC_SUBST(GTK_LIBS)
+AC_SUBST(GTK_CFLAGS)
dnl Check for libxml
AC_PATH_PROG(XML_CONFIG, xml-config, no)
@@ -926,12 +932,16 @@ if test "x$USE_DEBUG" = xyes; then
fi
if test "x$USE_PROFILING" = xyes; then
- CFLAGS="$CFLAGS -pg"
+ CFLAGS="$CFLAGS -pg -fprofile-arcs"
FOMIT_FRAME_POINTER=""
else
FOMIT_FRAME_POINTER="-fomit-frame-pointer"
fi
+dnl
+dnl AC_SUBST(FOMIT_FRAME_POINTER)
+dnl
+
if test "x$HAVE_LIBXV" = xyes; then
AC_DEFINE(HAVE_LIBXV)
fi
@@ -1024,6 +1034,7 @@ AM_CONDITIONAL(HAVE_NASM, test "x$HAVE_NASM" = "xyes")
AM_CONDITIONAL(HAVE_LIBGLADE_GNOME, test "x$HAVE_LIBGLADE_GNOME" = "xyes")
AM_CONDITIONAL(HAVE_GNOME, test "x$HAVE_GNOME" = "xyes")
AM_CONDITIONAL(HAVE_LIBXV, test "x$HAVE_LIBXV" = "xyes")
+AM_CONDITIONAL(HAVE_GTK, test "x$HAVE_GTK" = "xyes")
AM_CONDITIONAL(HAVE_GTK_DOC, $HAVE_GTK_DOC)
AM_CONDITIONAL(BUILD_DOCS, test "x$BUILD_DOCS" = "xyes")
AM_CONDITIONAL(BUILD_TESTS, test "x$BUILD_TESTS" = "xyes")
@@ -1176,6 +1187,7 @@ libs/getbits/Makefile
libs/putbits/Makefile
libs/idct/Makefile
libs/audio/Makefile
+libs/bytestream/Makefile
libs/control/Makefile
plugins/Makefile
plugins/a52dec/Makefile
@@ -1285,6 +1297,8 @@ test/Makefile
test/xml/Makefile
test/bindings/Makefile
dnl someone should fix this test/misc/Makefile
+test/memchunk/Makefile
+test/events/Makefile
tests/Makefile
tests/sched/Makefile
tests/eos/Makefile
diff --git a/docs/gst/tmpl/gstautoplug.sgml b/docs/gst/tmpl/gstautoplug.sgml
index ff407eac19..050429cf92 100644
--- a/docs/gst/tmpl/gstautoplug.sgml
+++ b/docs/gst/tmpl/gstautoplug.sgml
@@ -116,7 +116,7 @@ The type of the autoplugger.
-@name:
+@feature:
@longdesc:
@type:
@@ -207,22 +207,3 @@ The type of the autoplugger.
@Returns:
-
-
-
-
-
-@factory:
-@parent:
-@Returns:
-
-
-
-
-
-
-
-@parent:
-@Returns:
-
-
diff --git a/docs/gst/tmpl/gstbuffer.sgml b/docs/gst/tmpl/gstbuffer.sgml
index 9214caa7c5..94ccbc2a9e 100644
--- a/docs/gst/tmpl/gstbuffer.sgml
+++ b/docs/gst/tmpl/gstbuffer.sgml
@@ -239,6 +239,7 @@ used when data in a stream has been skipped
+@data_type:
@lock:
@data:
@size:
@@ -265,6 +266,8 @@ used when data in a stream has been skipped
@pool:
+@location:
+@size:
@Returns:
@@ -293,9 +296,12 @@ used when data in a stream has been skipped
+@buf:
+@buf2:
+@Returns:
+
@buffer:
@append:
-@Returns:
diff --git a/docs/gst/tmpl/gstbufferpool.sgml b/docs/gst/tmpl/gstbufferpool.sgml
index ddcf3dadf2..874a6501d6 100644
--- a/docs/gst/tmpl/gstbufferpool.sgml
+++ b/docs/gst/tmpl/gstbufferpool.sgml
@@ -52,30 +52,10 @@ A bufferpool can be requested from a pad with the gst_pad_get_bufferpool() funct
@lock:
-@new_user_data:
-@destroy_user_data:
-@destroy_buffer:
-
-
-
-The function called when a buffer has to be created for this pool.
-
-
-@pool: the pool from which to create the buffer
-@user_data: any user data
-@Returns: a new buffer from the pool
-
-
-
-
-This function will be called when the given buffer has to be returned to
-the pool.
-
-
-@pool: the pool to return the buffer to
-@buffer: the buffer to return
-@user_data: any user data
-
+@buffer_free:
+@buffer_copy:
+@destroy_hook:
+@user_data:
@@ -85,24 +65,6 @@ the pool.
@Returns:
-
-
-
-
-
-@pool:
-@Returns:
-
-
-
-
-
-
-
-@pool:
-@buffer:
-
-
@@ -130,26 +92,6 @@ the pool.
@pool:
-
-
-
-
-
-@pool:
-@create:
-@user_data:
-
-
-
-
-
-
-
-@pool:
-@destroy:
-@user_data:
-
-
@@ -163,9 +105,10 @@ the pool.
-@oldpool:
@buffer_size:
@pool_size:
@Returns:
+
+@oldpool:
diff --git a/docs/gst/tmpl/gstdisksrc.sgml b/docs/gst/tmpl/gstdisksrc.sgml
index a7d80b5896..1dae1ec21f 100644
--- a/docs/gst/tmpl/gstdisksrc.sgml
+++ b/docs/gst/tmpl/gstdisksrc.sgml
@@ -47,8 +47,8 @@ Specify how many bytes to read at a time.
Get/set the current offset in the file.
-
+
-Get the size of the file.
+
diff --git a/docs/gst/tmpl/gstelement.sgml b/docs/gst/tmpl/gstelement.sgml
index 8136a4d3cb..496724a3a7 100644
--- a/docs/gst/tmpl/gstelement.sgml
+++ b/docs/gst/tmpl/gstelement.sgml
@@ -225,7 +225,7 @@ of the element, the GtkType value for it, as well as a pointer to the
GstElementDetails struct for the element.
-@name:
+@feature:
@type:
@details:
@padtemplates:
@@ -241,14 +241,6 @@ circumstances.
@element: The element in question.
-
-
-
-
-
-@Returns:
-
-
@@ -503,14 +495,6 @@ circumstances.
@Returns:
-
-
-
-
-
-@elementfactory:
-
-
@@ -580,25 +564,6 @@ circumstances.
@Returns:
-
-
-
-
-
-@factory:
-@parent:
-@Returns:
-
-
-
-
-
-
-
-@parent:
-@Returns:
-
-
Is trigered whenever the state of an element changes
diff --git a/docs/gst/tmpl/gstfakesink.sgml b/docs/gst/tmpl/gstfakesink.sgml
index 81869b93ee..1aac92d45a 100644
--- a/docs/gst/tmpl/gstfakesink.sgml
+++ b/docs/gst/tmpl/gstfakesink.sgml
@@ -24,7 +24,7 @@ with the buffer. (fakesink)
@gstfakesink: the object which received the signal.
@arg1:
-
+
diff --git a/docs/gst/tmpl/gstfakesrc.sgml b/docs/gst/tmpl/gstfakesrc.sgml
index 9da569925b..323cb0b00d 100644
--- a/docs/gst/tmpl/gstfakesrc.sgml
+++ b/docs/gst/tmpl/gstfakesrc.sgml
@@ -22,12 +22,12 @@ The GstFakeSrc generates empty buffers. (fakesrc)
@gstfakesrc: the object which received the signal.
@arg1:
-
+
-
+
@@ -42,7 +42,7 @@ The GstFakeSrc generates empty buffers. (fakesrc)
-
+
diff --git a/docs/gst/tmpl/gstidentity.sgml b/docs/gst/tmpl/gstidentity.sgml
index c2309bb31e..70e5009b06 100644
--- a/docs/gst/tmpl/gstidentity.sgml
+++ b/docs/gst/tmpl/gstidentity.sgml
@@ -22,12 +22,12 @@ Pass data without modification.
@gstidentity: the object which received the signal.
@arg1:
-
+
-
+
diff --git a/docs/gst/tmpl/gstobject.sgml b/docs/gst/tmpl/gstobject.sgml
index 0698426108..6de54c918e 100644
--- a/docs/gst/tmpl/gstobject.sgml
+++ b/docs/gst/tmpl/gstobject.sgml
@@ -141,14 +141,6 @@ Check if the object has been destroyed.
@obj: The Object to check
-
-
-
-
-
-@Returns:
-
-
diff --git a/docs/gst/tmpl/gstpad.sgml b/docs/gst/tmpl/gstpad.sgml
index 85814e86ea..3c62b9afbb 100644
--- a/docs/gst/tmpl/gstpad.sgml
+++ b/docs/gst/tmpl/gstpad.sgml
@@ -189,24 +189,6 @@ a start/stop timecode pair.
@size: the size of the region to get
-
-
-The function that will be called when a QoS message is sent.
-
-
-@pad: the pad that sent the QoS message
-@qos_message: the message
-
-
-
-
-The function that will be called in an EOS case.
-
-
-@pad: the pad that needs to be set to EOS state
-@Returns: TRUE if EOS was successful, FALSE otherwise
-
-
The function that will be called when the caps of the pad has
@@ -247,25 +229,6 @@ The function that will be called when negotiating.
@Returns: The result of the negotiation process
-
-
-
-The function that will be called when pushing a buffers.
-
-
-@pad: the pad to push
-@buf: a GstBuffer to push
-
-
-
-
-The function that will be called when pulling buffers.
-
-
-@pad: the pad to pull
-@Returns: a GstBuffer
-
-
the region types for #gst_pad_pullregion.
@@ -383,24 +346,6 @@ Destroy the pad.
@nego:
-
-
-
-
-
-@pad:
-@qos:
-
-
-
-
-
-
-
-@pad:
-@eos:
-
-
@@ -627,32 +572,6 @@ Destroy the pad.
@Returns:
-
-
-
-
-
-@pad:
-@Returns:
-
-
-
-
-
-
-
-@pad:
-@qos_message:
-
-
-
-
-Call the EOS function of the pad
-
-
-@pad: the pad to call the eos function of.
-
-
@@ -706,15 +625,6 @@ Call the EOS function of the pad
@Returns:
-
-
-
-
-
-@pad:
-@Returns:
-
-
@@ -731,12 +641,12 @@ Call the EOS function of the pad
@len:
@sched:
@chainfunc:
+@chainhandler:
@getfunc:
+@gethandler:
+@eventfunc:
+@eventhandler:
@getregionfunc:
-@qosfunc:
-@eosfunc:
-@pushfunc:
-@pullfunc:
@pullregionfunc:
@negotiatefunc:
@newcapsfunc:
@@ -831,22 +741,6 @@ Get the getregion function of the real pad.
@pad: the real pad to query.
-
-
-Get the pushfunction of the real pad.
-
-
-@pad: the real pad to query.
-
-
-
-
-Get the pullfunction of the real pad.
-
-
-@pad: the real pad to query.
-
-
Get the pullregion function of the real pad.
@@ -855,22 +749,6 @@ Get the pullregion function of the real pad.
@pad: the real pad to query.
-
-
-Get the QoS function of the real pad.
-
-
-@pad: the real pad to query.
-
-
-
-
-Get the EOS function of the real pad.
-
-
-@pad: the real pad to query.
-
-
Get the negotiate function from the real pad.
diff --git a/docs/gst/tmpl/gstplugin.sgml b/docs/gst/tmpl/gstplugin.sgml
index 6d5d7bab6c..0668663d52 100644
--- a/docs/gst/tmpl/gstplugin.sgml
+++ b/docs/gst/tmpl/gstplugin.sgml
@@ -63,11 +63,9 @@ to bring it into memory.
@name:
@longname:
@filename:
-@types:
-@numtypes:
-@elements:
-@numelements:
-@numautopluggers:
+@features:
+@numfeatures:
+@module:
@@ -198,33 +196,6 @@ loaded will use this variable to initialize the plugin.
@Returns:
-
-
-
-
-
-@plugin:
-@factory:
-
-
-
-
-
-
-
-@plugin:
-@factory:
-
-
-
-
-
-
-
-@plugin:
-@factory:
-
-
@@ -242,59 +213,6 @@ loaded will use this variable to initialize the plugin.
@Returns:
-
-
-
-
-
-@plugin:
-@Returns:
-
-
-
-
-
-
-
-@plugin:
-@Returns:
-
-
-
-
-
-
-
-@plugin:
-@Returns:
-
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-
-@mime:
-
-
-
-
-
-
-
-@name:
-@Returns:
-
-
diff --git a/docs/gst/tmpl/gstqueue.sgml b/docs/gst/tmpl/gstqueue.sgml
index 923850a29b..afac6898d3 100644
--- a/docs/gst/tmpl/gstqueue.sgml
+++ b/docs/gst/tmpl/gstqueue.sgml
@@ -35,7 +35,7 @@ The queue blocks by default.
Get the number of buffers in the queue.
-
+
Specify the maximum number of buffers in the queue before the queue
blocks.
diff --git a/docs/gst/tmpl/gstreamer-unused.sgml b/docs/gst/tmpl/gstreamer-unused.sgml
index 21d14bc6f9..55f641d0eb 100644
--- a/docs/gst/tmpl/gstreamer-unused.sgml
+++ b/docs/gst/tmpl/gstreamer-unused.sgml
@@ -1,232 +1,26 @@
-
-
-
-
-
-@pad:
-@buf:
-
-
-
-Query the element for the current mime type
-
-
-
-
+
-
+
-
+
+
+
+
+
+GstElement
+
+
+
-
-
-
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@meta:
-
-
-
-
-
-
-@fromcaps:
-@tocaps:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-@pad:
-@parent:
-
-
-
-
-
-
-@pad:
-@buf:
-
-
-
-
-
-
-@pad:
-@buf:
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@pad:
-@buf:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-@elementfactory:
-@id:
-
-
-
-
-
-
-
-
-
-The number of channels.
-
-
-
-
-
-Use this macro to show debugging info. This is only usefull when developing new
-plugin elements.
-If you #define DEBUG_ENABLED before including gst/gst.h, this macro will produce
-g_print messages.
-
-
-@format: the format specification as in g_print
-@args...: arguments
-
-
-GstEsdSink
-
-
-
-
-
-
-
-
-
-
-
-
-
-@type:
-@parent:
-@Returns:
-
-
-
-
-
-
-@src:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-An eos signal is triggered whenever the GstSrc has reached the end of
-the stream.
-
-
-
-@gstsrc: the object which received the signal.
-@arg1: the object which received the signal
-
-
-
-
-
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-Provide context for buffers
-
-
-
-
-
+Information about audio buffers.
@@ -236,204 +30,36 @@ Provide context for buffers
-
-
+
+Information about audio buffers.
+
+
+audioraw
+
+
+
+
+Reads data from a file. You can seek to a specific location by setting
+the offset.
-@name_template:
-@direction:
-@presence:
-@caps:
-@Returns:
-
-
-
-
-
-@obj:
-
-
+
-
+
+GstAsyncDiskSrc
+
+
+
-@obj:
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-@pad:
-@parent:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-The filename to write to.
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-Specify how many bytes to read at a time.
-
-
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@connection:
-
-
-
-subclass use this to start their flag enumeration
-
-
-
-
-
-
-
-
-@audiosink:
-@channels:
-
-
-Generic connection between elements.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@bin:
-
-
-
-
-
-
-@element:
-@format:
-@args...:
-
-
-
-
-
-
-@meta:
-@format:
-@visual:
-@width:
-@height:
-@overlay_info:
-@dga_info:
-
-
-
-
-
-
-@meta:
@@ -441,942 +67,33 @@ Generic connection between elements.
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-@esdsink:
-@channels:
-
-
-
-
-
-
-@autoplug:
-@srcpad:
-@sinkpad:
-@Varargs:
-@Returns:
-@srccaps:
-@sinkcaps:
-
-
-
-
-
-
-@obj:
-
-
-
-Specify wether the queue blocks or not.
-
-
-
-
-
-
-
-
-@pad:
-@offset:
-@size:
-@Returns:
-
-
-
-
-
-
-@name:
-@fd:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@pad:
-@pull:
-
-
-
-
-
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@pad:
-@caps:
-
-
-
-Create a fourcc property out of an integer value.
-
-
-@a: the integer value
-
-
-
-
-
-
-
-
-
-
-
-
-@format:
-@args...:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@Returns:
-
-
-
-Specify the current offset in the file.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-@nextpad:
-@Varargs:
-@Returns:
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@meta:
-
-
-
-
-
-
-
-
-
-
-
-
-@base:
-@swidth:
-@sheight:
-@bytes_per_line:
-
-
-spectrum
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@src:
-
-
-
-
-
-
-@id:
-@sink:
-
-
-
-
-
-
-@obj:
-
-
-GstGetbits
-
-
-
-audioraw
-
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-@element:
-@parent:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@sinkid:
-@srcid:
-@Returns:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@id:
-@Returns:
-
-
-
-
-
-
-@esdsink:
-@frequency:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@cat:
-@format:
-@args...:
-
-
-
-
-
-
-@obj:
-
-
-
-The audio format as defined in soundcard.h
-
-
-
-
-
-
-
-
-@obj:
-
-
-GstAsyncDiskSrc
-
-
-
->>>>>>> 1.23.2.3
-
-
-
-
-
-
-
-
-
-
-@elementfactory:
-@id:
-
-
-
-
-
-
-@bin:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-The fequency.
-
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-The buffer is sent to the sound card.
-
-
-@gstaudiosink: the object which received the signal.
-@arg1: the audiosink.
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@pad:
-@buf:
-
-
-
-
-
-
-@buffer:
-@meta:
-
-
-
-
-
-
-@factory:
-@caps:
-@Returns:
-
-
-
-
-
-
-@pad:
-@buf:
-
-
-
-
-
-
-
-
-
-
-
-
-@buffer:
-@meta:
-
-
-
-
-
-
-@factory:
-@counter:
-@Returns:
-@count:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@cat:
-@element:
-@format:
-@args...:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-
-
-
-
-
-
-@id:
-@src:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-@esdsink:
-
-
-
-
-
-
-@connection:
-
-
-
-Is emited after the buffer has been written to the disk.
-
-
-@gstdisksink: the object which received the signal.
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-@element:
-@manager:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-GstFilter
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@pad:
-@Returns:
-
-
-
-
-
-
-@thread:
-
-
-
-
-
-
-@x1:
-@x2:
-@y1:
-@y2:
-
-
-
-Flags for the GstSrc element
-
-
-@GST_SRC_ASYNC: Indicates that this src is asynchronous
-@GST_SRC_FLAG_LAST: subclasses can use this to number their flags
-
-
-GstColorSpace
+
+GstAudioSink
-
-
-Defines an entry for a padfactory.
-
-
-
-
-
-
-
-
-
-GST_ASYNCDISKSRC_OPEN
-the asyncdisksrc is open for reading
-
-
-
-
-
-
-@GST_ASYNCDISKSRC_OPEN:
-@GST_ASYNCDISKSRC_FLAG_LAST:
-
-
+
-
-
-
-
-
-@element:
-@state:
-@Returns:
-
-
-
-
-
-
-@pad:
-@Returns:
-
-
+
-
-
-
-
-
-@obj:
-
-
-
-subclasses can use this value to start the enumeration of their flags
-
+
-
-Frequencies of a spectrum analysis.
+
+GstAudioSrc
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@klass:
-
-
-
-Indicates a sinkpad for the padfactory.
-
-
-
-
-
-
-
-
-@klass:
@@ -1384,117 +101,24 @@ Indicates a sinkpad for the padfactory.
-
-
-
-
-
-@parent:
-@Returns:
-
-
-
-
-
-
-@pad:
-@Returns:
-
-
+
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-Retrieve the flags of the given meta information.
-
-
-@meta: the meta information
-
-
-
-
-
-
-@element:
-@templ:
-@Returns:
-@temp:
-
-
-
-
-
-
-@obj:
-
-
-The end point of a filter graph
-
-
-
-
-
-
-
-@meta:
-@format:
-@channels:
-@frequency:
-@bps:
-
-
-
-The number of channels (mono, stereo, ...)
-
-
-
-
-
-
-
-
-
-
-
-This macro checks to see if the given state is set.
-
-
-@obj: Element to check for state.
-@flag: State to check for, must be a single bit in guint32.
-
-
-
-
-
-
-@lock: for locking purposes
-@flags: the flags of the meta data
-@data: the meta data
-@size: the size of the meta data
-
-
-
-
-
-
-@buffer:
-@size:
-@root:
-@Returns:
-
-
+
+
+
+
+
+GstColorSpace
+
+
+
+A connection is a bas class for a generic connection between
+elements. A connection is typically a bas class for queues.
@@ -1505,347 +129,76 @@ This macro checks to see if the given state is set.
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-GstAudioSink
+
+Generic connection between elements.
-
-
+
+GstConnection
-
-@obj:
-
-
-
-This macro sets the given flags.
-
-
-@src:
-@flag: Flag to set, can by any number of bits in guint32.
-@obj: GstSrc to set flag in.
-
-
-
-Retrieves the type id of the data in the buffer.
-
-
-@buf: GstBuffer
-
-
-
-
-
-
-@a:
-
-
+
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@name:
-@Returns:
-
-
+
-
-GstSink
+
-
+
+
+GstEsdSink
+
+
+
-A flag indicating that MMX instructions are supported.
+Filters take data in and spit data out. They are the main Element in a filter graph.
+Filters have zero or more inputs and zero or more outputs. Filters are connected
+together to form filter graphs. A GstFilter is the base class and is not very usefull
+on its own.
-
-
-
-
-
-@Returns:
-
-
+
-
-
-
-
-
-@factory:
-@caps:
-@Returns:
-
-
-
-This macro usets the given flags.
-
-
-@src:
-@flag: Flag to set, must be a single bit in guint32.
-@obj: GstSrc to unset flag in.
-
-
-
-The frequency.
-
+
+Take data in and spit data out
-
-
-Indicates a srcpad for the padfactory.
-
+
+GstFilter
-
+
-
-
-
-
-
-@buffer:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@obj:
-
-
+
-
-
+
-
-
-
+
+GstGetbits
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@pad:
-@name:
-@Returns:
-
-
-
-
-
-
-
-
-
-
-
-
-@esdsink:
-@format:
-
-
-
-
-
-
-@cat:
-@format:
-@args...:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@obj:
-
-
-
-The maximum number of cothreads we are going to support.
-
-
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-Starts the declaration of a the capabilities for this padtemplate.
-
-
-@a...: a capability factory
-
-
-GstSrc
-
-
-
-
-
-
-
-@pad:
-@Returns:
-
-
-
-
-
-
-@pad:
-@buf:
-
-
-
-
-
-
-@name:
-@mime:
-@props:
-@Returns:
-
-
-
-The Element is going from the READY state to the PLAYING state.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@arg:
@@ -1946,95 +299,18 @@ it, is there?
-
-GstConnection
-
-
-
+
-
-
-
-
+
+Provide context for buffers
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-GstElement
-
-
-
-
-
-
-
-@id:
-@Returns:
-
-
-
-
-
-
-@buf:
-
-
-
-
-
-
-
-
-
-Clear a flag in the meta data.
-
-
-@meta: the meta data
-@flag: the flag to clear
-
-
-
-
-
-
-@obj:
-
-
-
-
-
+
+GstMeta
@@ -2045,41 +321,149 @@ or a video card.
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@Returns:
-
-
+
-
+
+The end point of a filter graph
+
+
+
+GstSink
+
+
+
+
+A GstSrc is the start of a filter graph. It typically is a file or an
+audio source. It provides data for the next element in the graph.
+
+
+
+
+
-
+
+The start point of a filter graph
+
+
+
+GstSrc
+
+
+
-Query whether this object has multiple input pads.
-@obj: Element to query for multiple input pads.
-
+
+
+
+
+
+
+
+
+
+
+
+plugin
+
+
+
+
+Frequencies of a spectrum analysis.
+
+
+
+
+
+
+
+
+
+
+
+Frequencies of a spectrum analysis.
+
+
+
+spectrum
+
+
+
+
+Information about video buffers.
+
+
+
+
+
+
+
+
+
+
+Information about video buffers.
+
+
+
+videoraw
+
+
+
+
+The maximum number of cothreads we are going to support.
+
+
+
+
+
+The default stack size of a cothread.
+
+
+
+
+
+Use this macro to show debugging info. This is only usefull when developing new
+plugin elements.
+If you #define DEBUG_ENABLED before including gst/gst.h, this macro will produce
+g_print messages.
+
+
+@format: the format specification as in g_print
+@args...: arguments
+
+
+
+
+
+
+@format:
+@args...:
+
+
+
+
+
+
+
+
+
+
+
+
+@format:
+@args...:
+
+
@@ -2093,97 +477,111 @@ Query whether this object has multiple input pads.
@format:
@args...:
-
+
+@format:
+@args...:
-
+
-
-
-
-
-
-
-@factory:
-@Returns:
-
-
-
-
-
-
-
-
-
-
-
-
-@self:
-@parent:
-@Returns:
-@elements:
-
-
-
-
-
-
-@src:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Information about video buffers.
-
-
-
-
-
-
-
-
-@bin:
@element:
+@format:
+@args...:
-
+
-@name:
-@Returns:
+@element:
+@object:
+@format:
+@args...:
-
+
+
+
+
+
+@obj:
+
+
@klass:
-
+
+@obj:
-
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@buf:
+
+
+
+
+
+
+@buf:
+
+
+
+Retrieves the type id of the data in the buffer.
+
+
+@buf: GstBuffer
+
+
@@ -2197,100 +595,17 @@ Information about video buffers.
@klass:
-
+
-
+A flag indicating that MMX instructions are supported.
-
+
-
+A flag indicating that SSE instructions are supported.
-@name:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-Filters take data in and spit data out. They are the main Element in a filter graph.
-Filters have zero or more inputs and zero or more outputs. Filters are connected
-together to form filter graphs. A GstFilter is the base class and is not very usefull
-on its own.
-
-
-
-
-
-
-
-
-@tee:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-The Element is going from the PLAYING state to the READY state.
-
-
-
-
-
-
-
-
-@obj:
@@ -2298,7 +613,90 @@ Combine #GST_DEBUG_ENTER and #GST_DEBUG_SET_STRING.
-
+
+
+
+
+
+
+
+
+
+
+
+@cat:
+@format:
+@args...:
+
+
+
+
+
+
+@cat:
+@format:
+@args...:
+
+
+
+Set the debug string for the current function, typically containing the arguments
+to the current function, i.e. "('element')"
+
+
+@format: printf-style format string
+@args...: printf arguments
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+Query whether this object has multiple input pads.
+
+
+
+@obj: Element to query for multiple input pads.
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass: <<<<<<< gstreamer-unused.sgml
+
+
@@ -2312,19 +710,264 @@ Combine #GST_DEBUG_ENTER and #GST_DEBUG_SET_STRING.
@klass:
-
+
+@obj:
-
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+subclass use this to start their flag enumeration
+
+
+>>>>>>> 1.23.2.3
+
-
-videoraw
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
@@ -2333,6 +976,1348 @@ videoraw
@obj:
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@meta:
+
+
+
+Retrieve the flags of the given meta information.
+
+
+@meta: the meta information
+
+
+
+Check if a given flag is set.
+
+
+@meta: the meta data to test
+@flag: the flag to test
+
+
+
+Set a flag in the meta data.
+
+
+@meta: the meta data
+@flag: the flag to set
+
+
+
+Clear a flag in the meta data.
+
+
+@meta: the meta data
+@flag: the flag to clear
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+subclasses can use this value to start the enumeration of their flags
+
+
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+Indicate that this pad will always be available.
+Use this in the factory definition.
+
+
+
+
+
+Starts the declaration of a the capabilities for this padtemplate.
+
+
+@a...: a capability factory
+
+
+
+Indicates that this pad will be available on request. Use
+this in the factory definition.
+
+
+
+
+
+Indicates a sinkpad for the padfactory.
+
+
+
+
+
+Indicate that this pad will become available depending
+on the media type. Use this in the factory definition.
+
+
+
+
+
+Indicates a srcpad for the padfactory.
+
+
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+
+
+
+
+
+
+@a:
+@b:
+
+
+
+
+
+
+@a:
+
+
+
+
+
+
+
+
+
+Create a fourcc property out of an integer value.
+
+
+@a: the integer value
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+Get the EOS function of the real pad.
+
+
+@pad: the real pad to query.
+
+
+
+Get the pullfunction of the real pad.
+
+
+@pad: the real pad to query.
+
+
+
+Get the pushfunction of the real pad.
+
+
+@pad: the real pad to query.
+
+
+
+Get the QoS function of the real pad.
+
+
+@pad: the real pad to query.
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+
+
+
+
+
+
+@obj:
+
+
+
+This macro checks to see if the GST_SRC_ASYNC flag is set.
+
+
+@obj: GstSrc to check for flag in.
+
+
+
+
+
+
+@klass:
+
+
+
+This macro returns the entire set of flags for the object.
+
+
+@obj: GstSrc to return flags for.
+
+
+
+Query a GstSrc for the ASYNC flag
+
+
+@obj: The GstSrc to query
+
+
+
+This macro sets the given flags.
+
+
+@src:
+@flag: Flag to set, can by any number of bits in guint32.
+@obj: GstSrc to set flag in.
+
+
+
+This macro usets the given flags.
+
+
+@src:
+@flag: Flag to set, must be a single bit in guint32.
+@obj: GstSrc to unset flag in.
+
+
+
+This macro checks to see if the given state is set.
+
+
+@obj: Element to check for state.
+@flag: State to check for, must be a single bit in guint32.
+
+
+
+The Element is going from the PLAYING state to the READY state.
+
+
+
+
+
+The Element is going from the READY state to the PLAYING state.
+
+
+
+
+
+This macro sets the given state on the element.
+
+
+@obj: Element to set state of.
+@flag: State to set, can be any number of bits in guint32.
+
+
+
+This macro unsets the given state on the element.
+
+
+@obj: Element to unset state of.
+@flag: State to unset, can be any number of bits in guint32.
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+
+
+
+
+@obj:
+
+
+
+
+
+
+@klass:
+
+
+>>>>>>> 1.23.2.3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Specify how many bytes to read at a time.
+
+
+
+
+
+Get the size of the current file.
+
+
+
+
+
+Specify the location of the file to read.
+
+
+
+
+
+Specify the current offset in the file.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+GST_ASYNCDISKSRC_OPEN
+the asyncdisksrc is open for reading
+
+
+
+
+
+
+@GST_ASYNCDISKSRC_OPEN:
+@GST_ASYNCDISKSRC_FLAG_LAST:
+
+
+
+
+
+
+
+
+
+The buffer is sent to the sound card.
+
+
+@gstaudiosink: the object which received the signal.
+@arg1: the audiosink.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The number of bytes per read.
+
+
+
+
+
+The number of channels (mono, stereo, ...)
+
+
+
+
+
+Get the current number of bytes read.
+
+
+
+
+
+The audio format as defined in soundcard.h
+
+
+
+
+
+The frequency.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The function called when a buffer has to be created for this pool.
+
+
+@pool: the pool from which to create the buffer
+@user_data: any user data
+@Returns: a new buffer from the pool
+
+
+
+This function will be called when the given buffer has to be returned to
+the pool.
+
+
+@pool: the pool to return the buffer to
+@buffer: the buffer to return
+@user_data: any user data
+
+
+
+
+
+
+@GST_CAPS_ALWAYS:
+@GST_CAPS_MAYBE:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Is emited after the buffer has been written to the disk.
+
+
+@gstdisksink: the object which received the signal.
+
+
+
+
+
+
+
+
+
+The filename to write to.
+
+
+
+
+
+
+
+
+
+
+
+Get the size of the file.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@lock: for locking purposes
+@flags: the flags of the meta data
+@data: the meta data
+@size: the size of the meta data
+
+
+
+Flags indicating properties about the meta data.
+
+
+@GST_META_FREEABLE: the meta data can be freed
+
+
+
+
+
+
+
+
+
+Indicates this pad is active
+
+
+
+
+
+
+
+
+
+<<<<<<< gstreamer-unused.sgml
+
+
+
+
+The function that will be called in an EOS case.
+
+
+@pad: the pad that needs to be set to EOS state
+@Returns: TRUE if EOS was successful, FALSE otherwise
+
+
+
+Defines an entry for a padfactory.
+
+
+
+
+
+The padfactory.
+
+
+
+
+
+The function that will be called when pulling buffers.
+
+
+@pad: the pad to pull
+@Returns: a GstBuffer
+
+
+
+
+The function that will be called when pushing a buffers.
+
+
+@pad: the pad to push
+@buf: a GstBuffer to push
+
+
+
+The function that will be called when a QoS message is sent.
+
+
+@pad: the pad that sent the QoS message
+@qos_message: the message
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@GST_PROPS_END_ID_NUM:
+@GST_PROPS_LIST_ID_NUM:
+@GST_PROPS_INT_ID_NUM:
+@GST_PROPS_INT_RANGE_ID_NUM:
+@GST_PROPS_FOURCC_ID_NUM:
+@GST_PROPS_BOOL_ID_NUM:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Specify wether the queue blocks or not.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The number of channels.
+
+
+
+
+
+The fequency.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+An eos signal is triggered whenever the GstSrc has reached the end of
+the stream.
+
+
+
+@gstsrc: the object which received the signal.
+@arg1: the object which received the signal
+
+
+
+
+
+
+
+
+
+Flags for the GstSrc element
+
+
+@GST_SRC_ASYNC: Indicates that this src is asynchronous
+@GST_SRC_FLAG_LAST: subclasses can use this to number their flags
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Query the element for the current mime type
+
+
+
+
+
+Is trigered whenever the state of an element changes
+
+
+@gstelement: the object which received the signal.
+@arg1: the new state of the object
+
+
+
+
+
+
+@cat:
+@format:
+@args...:
+
+
+
+
+
+
+@cat:
+@element:
+@format:
+@args...:
+
+
+
+
+
+
+@meta:
+@format:
+@channels:
+@frequency:
+@bps:
+
+
+
+
+
+
+@meta:
+@bands:
+@channels:
+@interleaved:
+@lowfreq:
+@highfreq:
+@steps:
+
+
+
+
+
+
+@base:
+@swidth:
+@sheight:
+@bytes_per_line:
+
@@ -2348,13 +2333,58 @@ videoraw
@did_overlay:
@fully_obscured:
-
+
+
+
+
+
+@meta:
+@format:
+@visual:
+@width:
+@height:
+@overlay_info:
+@dga_info:
+
+
+
+
+
+
+@x1:
+@x2:
+@y1:
+@y2:
+
+
-
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@pad:
+@buf:
+
+
+
+
+
+
+@Returns:
+
+
@@ -2362,247 +2392,21 @@ videoraw
@name:
@Returns:
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-This macro returns the entire set of flags for the object.
-
-
-@obj: GstSrc to return flags for.
-
-
-
-
-
-
-
-
-
-Get the size of the current file.
-
-
-
-
-
-
-
-
-The start point of a filter graph
-
-
-
-
-
-
-
-@src:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@src:
-
-
-
-
-
-
-@bin:
-
-
-
-
-
-
-@factory:
-@counter:
-@Returns:
-
-
-
-
-
-
-
-
-
-
-
-
-@a:
-@b:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-
-
-
-The default stack size of a cothread.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-@klass: <<<<<<< gstreamer-unused.sgml
-
-
-
-Indicates that this pad will be available on request. Use
-this in the factory definition.
-
-
-
-
+
@audiosink:
+@channels:
-
+
-@obj:
-
-
-
-This macro unsets the given state on the element.
-
-
-@obj: Element to unset state of.
-@flag: State to unset, can be any number of bits in guint32.
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-@pad:
-@id:
-
-
-
-Indicate that this pad will always be available.
-Use this in the factory definition.
-
-
-
-
-
-
-
-
-@pad:
-@parent:
+@audiosink:
+@format:
@@ -2612,232 +2416,21 @@ Use this in the factory definition.
@audiosink:
@frequency:
-
+
+@audiosink:
-
-
-
-
-
-@elementfactory:
-
-
-
-The number of bytes per read.
-
-
-
-
-
-
-
-@argc:
-@argv:
-@Returns:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@size:
-@Returns:
-
-
-
-
-
-
-@element:
-@object:
-@format:
-@args...:
-
-
+
@Returns:
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@klass:
-
-
-
-A connection is a bas class for a generic connection between
-elements. A connection is typically a bas class for queues.
-
-
-
-
-
-
-
-
-
-@buf:
-
-
-
-Query a GstSrc for the ASYNC flag
-
-
-@obj: The GstSrc to query
-
-
-
-
-
-
-@obj:
-
-
-
-This macro sets the given state on the element.
-
-
-@obj: Element to set state of.
-@flag: State to set, can be any number of bits in guint32.
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-
-
-
-Flags indicating properties about the meta data.
-
-
-@GST_META_FREEABLE: the meta data can be freed
-
-
-
-
-
-
-
-
-
-
-
-
-@obj:
-
-
-Information about video buffers.
-
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@src:
-@offset:
-@size:
-
-
-
-
-
-
-
-
-
-
-
-
-@format:
-@args...:
-
-
-
-Is trigered whenever the state of an element changes
-
-
-@gstelement: the object which received the signal.
-@arg1: the new state of the object
-
-
-
-
-
-
-@klass:
-
-
+
@@ -2845,112 +2438,59 @@ Is trigered whenever the state of an element changes
@name:
@Returns:
-
+
+@src:
+
+
+
+
+
+
+@autoplug:
+@srcpad:
+@sinkpad:
+@Varargs:
+@Returns:
+@srccaps:
+@sinkcaps:
+
+
+
+
+
+
+@parent:
@Returns:
-
-Information about audio buffers.
-
-
-
+
-
-
-Take data in and spit data out
-
-
-
-
-The padfactory.
-
-
-
-
-
-This macro checks to see if the GST_SRC_ASYNC flag is set.
-
-
-@obj: GstSrc to check for flag in.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-GstMeta
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-A flag indicating that SSE instructions are supported.
-
-
-
-
-
-
-
-
-@obj:
-
-
-
-
-
-
-@object:
-@argname:
+@factory:
+@parent:
@Returns:
-
+
+@bin:
+@element:
-
+
+@bin:
-
-
-Set the debug string for the current function, typically containing the arguments
-to the current function, i.e. "('element')"
-
-
-@format: printf-style format string
-@args...: printf arguments
-
-
+
@@ -2965,196 +2505,44 @@ to the current function, i.e. "('element')"
@bin:
@element:
-
+
+@bin:
-
-
-Set a flag in the meta data.
-
-
-@meta: the meta data
-@flag: the flag to set
-
-
+
-@obj:
+@bin:
-
-
-Information about audio buffers.
-
-
-
-
+
-@GST_PROPS_END_ID_NUM:
-@GST_PROPS_LIST_ID_NUM:
-@GST_PROPS_INT_ID_NUM:
-@GST_PROPS_INT_RANGE_ID_NUM:
-@GST_PROPS_FOURCC_ID_NUM:
-@GST_PROPS_BOOL_ID_NUM:
+@element:
+@manager:
-
+
-@GST_CAPS_ALWAYS:
-@GST_CAPS_MAYBE:
+@buffer:
+@meta:
-
-
-Check if a given flag is set.
-
-
-@meta: the meta data to test
-@flag: the flag to test
-
-
+
-
-<<<<<<< gstreamer-unused.sgml
-
-
-
-
-
-
-
-
-
->>>>>>> 1.23.2.3
-
-
-
-
-@obj:
-
-
-
-
-
-
-
-
-
-Create new meta data.
-
-
-@type: the type of the meta data to create
-
-
-
-
-
-
-
-
-
-
-
-
-@factory:
+@buffer:
@Returns:
-
-
-Specify the location of the file to read.
-
-
-
-
-
-
-
-
-@klass:
-
-
-
-
-
-
-@Returns:
-
-
-
-
-
-
-@format:
-@args...:
-
-
-
-
-
-
-@audiosink:
-@format:
-
-
-
-Frequencies of a spectrum analysis.
-
-
-
-
-
-GstAudioSrc
-
-
-
-
-Indicate that this pad will become available depending
-on the media type. Use this in the factory definition.
-
-
-
-
-
-
-
-
-@cat:
-@format:
-@args...:
-
-
-
-Reads data from a file. You can seek to a specific location by setting
-the offset.
-
-
-
-
-
-
-
-
-@name:
-@Returns:
-
-
-
-
-
-
-@obj:
-
@@ -3163,11 +2551,693 @@ the offset.
@buffer:
@Returns:
-
+
-Get the current number of bytes read.
+
+@pool:
+@buffer:
+
+
+
+
+
+
+@pool:
+@Returns:
+
+
+
+
+
+
+@pool:
+@create:
+@user_data:
+
+
+
+
+
+
+@pool:
+@destroy:
+@user_data:
+
+
+
+
+
+
+@buffer:
+@meta:
+
+
+
+
+
+
+@fromcaps:
+@tocaps:
+@Returns:
+
+
+
+
+
+
+@name:
+@mime:
+@props:
+@Returns:
+
+
+
+
+
+
+@factory:
+@Returns:
+
+
+
+
+
+
+@factory:
+@counter:
+@Returns:
+@count:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@connection:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@element:
+@state:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@self:
+@parent:
+@Returns:
+@elements:
+
+
+
+
+
+@argc:
+@argv:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@element:
+@templ:
+@Returns:
+@temp:
+
+
+
+
+
+
+@element:
+@parent:
+@Returns:
+
+
+
+
+
+
+@elementfactory:
+@id:
+
+
+
+
+
+
+@elementfactory:
+@id:
+
+
+
+
+
+
+@factory:
+@caps:
+@Returns:
+
+
+
+
+
+
+@factory:
+@caps:
+@Returns:
+
+
+
+
+
+
+@elementfactory:
+
+
+
+
+
+
+@parent:
+@Returns:
+
+
+
+
+
+
+@elementfactory:
+
+
+
+
+
+
+@factory:
+@parent:
+@Returns:
+
+
+
+
+
+
+@pad:
+@buf:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@esdsink:
+@channels:
+
+
+
+
+
+
+@esdsink:
+@format:
+
+
+
+
+
+
+@esdsink:
+@frequency:
+
+
+
+
+
+
+@esdsink:
+
+
+
+
+
+
+@pad:
+@buf:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@src:
+
+
+
+
+
+
+@pad:
+@buf:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@name:
+@fd:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@pad:
+@buf:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+Create new meta data.
+
+
+@type: the type of the meta data to create
+
+
+
+
+
+
+@size:
+@Returns:
+
+
+
+
+
+
+@meta:
+
+
+
+
+
+
+@meta:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@pad:
+@parent:
+
+
+
+Call the EOS function of the pad
+
+
+@pad: the pad to call the eos function of.
+
+
+
+
+
+
+@pad:
+@Returns:
+
+
+
+
+
+
+@pad:
+@name:
+@Returns:
+
+
+
+
+
+
+@pad:
+@Returns:
+
+
+
+
+
+
+@pad:
+@Returns:
+
+
+
+
+
+
+@pad:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@pad:
+@Returns:
+
+
+
+
+
+
+@pad:
+@qos_message:
+
+
+
+
+
+
+@pad:
+@offset:
+@size:
+@Returns:
+
+
+
+
+
+
+@pad:
+@parent:
+
+
+
+
+
+
+@pad:
+@parent:
+@Returns:
+
+
+
+
+
+
+@nextpad:
+@Varargs:
+@Returns:
+
+
+
+
+
+
+@pad:
+@caps:
+
+
+
+
+
+
+@pad:
+@Returns:
+
+
+
+
+
+
+@pad:
+@eos:
+
+
+
+
+
+
+@pad:
+@pull:
+
+
+
+
+
+
+@pad:
+@qos:
+
+
+
+
+
+
+@pad:
+@id:
+
+
+
+
+
+
+@name_template:
+@direction:
+@presence:
+@caps:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@plugin:
+@factory:
+
+
+
+
+
+
+@plugin:
+@factory:
+
+
+
+
+
+
+@plugin:
+@factory:
+
+
+
+
+
+
+@plugin:
+@Returns:
+
+
+
+
+
+
+@plugin:
+@Returns:
+
+
+
+
+
+
+@plugin:
+@Returns:
@@ -3175,35 +3245,210 @@ Get the current number of bytes read.
-
+
-@meta:
-@bands:
-@channels:
-@interleaved:
-@lowfreq:
-@highfreq:
-@steps:
+@name:
+@Returns:
-
-plugin
-
-
-
+
-@obj:
+@name:
+@Returns:
-
+
+@mime:
+
+
+
+
+
+
+@factory:
+@Returns:
+
+
+
+
+
+
+@factory:
+@counter:
+@Returns:
+
+
+
+
+
+
+@pad:
+@buf:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@connection:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@src:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@src:
+
+
+
+
+
+
+@src:
+@offset:
+@size:
+
+
+
+
+
+
+@src:
+
+
+
+
+
+
+@pad:
+@buf:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@tee:
+@Returns:
+
+
+
+
+
+
+@Returns:
+
+
+
+
+
+
+@thread:
+
+
+
+
+
+
+@arg:
+
+
+
+
+
+
+@id:
+@sink:
+
+
+
+
+
+
+@id:
+@src:
@@ -3211,49 +3456,114 @@ plugin
-
+
+
+
+
+
+@sinkid:
+@srcid:
+@Returns:
+
+
+
+
+
+
+@id:
+@Returns:
+
+
+
+
+
+
+@id:
+@Returns:
+
+
-
+
-@klass:
+@parent:
+@Returns:
-
+
-@klass:
+@type:
+@parent:
+@Returns:
-
+
-@obj:
+@parent:
+@Returns:
-
+
-Indicates this pad is active
+
+@factory:
+@parent:
+@Returns:
-
+
+
+
+
+
+@object:
+@argname:
+@Returns:
+
+
+
+
+
+
+@buffer:
+@size:
+@root:
+@Returns:
+
+
-
+
+
+
+
+
+@name:
+@Returns:
+
+
+
+
+
+
+@name:
+@Returns:
+
+
-A GstSrc is the start of a filter graph. It typically is a file or an
-audio source. It provides data for the next element in the graph.
diff --git a/docs/gst/tmpl/gsttee.sgml b/docs/gst/tmpl/gsttee.sgml
index 31527214b3..972d8244fe 100644
--- a/docs/gst/tmpl/gsttee.sgml
+++ b/docs/gst/tmpl/gsttee.sgml
@@ -14,7 +14,7 @@ A tee can be used to split out the filter graph.
-
+
diff --git a/docs/gst/tmpl/gstthread.sgml b/docs/gst/tmpl/gstthread.sgml
index bc4f3af839..29151cb704 100644
--- a/docs/gst/tmpl/gstthread.sgml
+++ b/docs/gst/tmpl/gstthread.sgml
@@ -45,7 +45,7 @@ Thread flags:
@Returns:
-
+
TRUE if the thread should be created.
diff --git a/docs/gst/tmpl/gsttype.sgml b/docs/gst/tmpl/gsttype.sgml
index 472d244f44..9b2ec82daa 100644
--- a/docs/gst/tmpl/gsttype.sgml
+++ b/docs/gst/tmpl/gsttype.sgml
@@ -71,13 +71,14 @@ A type.
@id:
@mime:
@exts:
-@typefindfuncs:
+@factories:
The struct with the typefactory information.
+@feature:
@mime:
@exts:
@typefindfunc:
@@ -126,22 +127,3 @@ The struct with the typefactory information.
@Returns:
-
-
-
-
-
-@parent:
-@Returns:
-
-
-
-
-
-
-
-@factory:
-@parent:
-@Returns:
-
-
diff --git a/docs/random/wtay/events b/docs/random/wtay/events
index 2e9b7c5a50..5498a68faa 100644
--- a/docs/random/wtay/events
+++ b/docs/random/wtay/events
@@ -1,140 +1,138 @@
-some random ramblings about the event system:
+This is a round up from our IRC session on events. It's open for
+discussion of course.
-Possible candidates for events
+Definition
+----------
+
+The event system is designed to be a mechanism for _inter_plugin_
+communication. Their scope is therefore limited in a way that they do
+not serve as a way to communicate between plugins and the app (signals
+and properties are still used for plugin-app communication).
+
+Events will be generated by either a plugin or the app. It should be
+possible for a plugin to generate an event on one of its pads and it
+should be possible for an app to insert an event on an abitrary pad in
+the pipeline.
+
+
+Event handling
+--------------
+
+Events can both travel upstream or downstream. Some events, by nature,
+only travel in one direction.
+
+* downstream events
+
+ - Travel in the same way buffers do. This includes that they are handled
+ by the scheduler. The rationale is that the events should be kept
+ as close to the buffers are possible.
+
+ - plugins should check the type of the GstData passed in the _chain
+ or _loop function and act appropriatly. This can be done by either
+ doing their own stuff or by calling the default handler.
+
+ - are handled on the sink pad.
+
+* upstream events
+
+ - are handled with an event handler attached to the srcpad. A default
+ handler will be implemented for pads that don't implement their own
+ handler.
+
+ - travel as fast as possible. the rationale is that a seek event should
+ get to the src element ASAP.
+
+
+Possible candidates for events
------------------------------
- QoS
+ quality of service. Plugins can notify other plugins about the quality
+ of the pipeline. A video element can for example say that it receives
+ too much frames and that plugins connected to it need to slow down.
+
- EOS
+ A plugin can notify other plugins that it has run out-of-data.
+
- Seek
- - caps nego??
- - bufferpool get??
+ Used to notify plugins that they need to seek to a certain byte offset
+ or timestamp.
+
+ - discontinuous
+ A plugin has detected a discontinuity in the stream. Other plugins
+ might need to resync.
+
+ - flush
+ Plugins need to get rid of any buffered data ASAP.
+
+ - caps nego??
+ - bufferpool get??
- ...
-Assumptions for events
-----------------------
-- They are tied to a pad.
-- get rid of gst_pad_set_*_function (except for the chain/get ones)
-- occur async to dataflow. (need locking?)
-- fixed set of events only for core features. (elements cannot abuse
- events for doing dataflow)
+application generated events
+----------------------------
-Questions
+The application can insert events into the pipeline at arbirary
+places. This will be done by calling gst_pad_event() on a pad.
+
+A first implementation will only cover inserting events on src pads
+since inserting events on sinkpads needs changes to the scheduler.
+
+
+Effects of events on plugins
+----------------------------
+
+some events are going to change the state of an element. The EOS event
+will for example change the state of an element to the PAUSED state. Not
+sure when or how this will happen.
+
+
+use cases
---------
-limit the valid directions an event can travel in? ie. Can EOS only
-travel downstream (left to right)?
+1) filesrc ! fakesink
-eg. Seek travels upstream, but it makes sense to also make it travel
- downstream (the case of a disksink, where we overwrite the header)
+filesrc will read until it reaches EOF. It will then create a GstEvent
+of type EOS and return it in the _get function. The event will travel
+downstream and will reach the fakesink element. Fakesink will detect
+the event in the _chain function and will call the default handler. The
+default handler will set the element to the paused state. filesrc will
+eventually change its state to PAUSED, probably before sending out the
+event (TBD)
+
+2) filesrc ! fakesink
+
+The app wants to perform a seek on filesrc. It'll call the gst_pad_event()
+on filesrcs src pad with the SEEK event type. The event handler will
+react and change filesrcs internal status. filesrc will return a DISCONT
+event before returning the buffer with the new offset.
+
+3) filesrc ! mpeg2parse video_0! queue ! { mpeg2dec ! xvideosink }
+
+lost of possibilities here: The app can choose to insert a seek event
+on the filesrc element (byte offset), it can insert a byte/time offset
+seek on the video_0 pad of mpeg2parse or it can insert a time seek event
+on mpeg2decs src pad.
+
+the event will travel upstream using the handlers and the intermediate
+elements can convert the event from a time to a byte offset (possibly
+using GstTimeCache to speed up things).
+
+Filesrc will get a byte seek event on its src pad and will proceed as
+in case 2.
+
+As can be seen from this example the app will generate an event in another
+context than those of the plugins, so this will need proper locking.
+
+The app can also choose to insert a flush event on one of the src
+pads. The plugins would clear their cached data and forward the event
+to their upstream peer pad(s).
+
+4)...
+
+Insert impossible case here..
-Setting an event function
--------------------------
-
-void gst_pad_set_event_function (GstPad *pad, gint event_mask,
- GstEventFunction *function);
-event masks:
-
-typedef enum {
- GST_EVENT_EOS = (1 << 0),
- GST_EVENT_QOS = (1 << 1),
- GST_EVENT_SEEK = (1 << 2),
- GST_EVENT_CAPS = (1 << 3),
-} GstEventType;
-
-Event structure
----------------
-
-typedef struct {
- GstEventType type;
- GstEventMinorType minor;
- guint64 timestamp; /* also sequence number ?? */
-
- union {
- /* EOS stuff */
- /* QoS stuff */
- /* Seek stuff */
- GstSeekType type; /* time, bytes, ... */
- gint64 offset;
- gint64 lenth;
- /* Caps stuff */
- GstCaps *caps;
- } data;
-} GstEvent;
-
-
-typedef enum {
- GST_EVENT_MINOR_NONE,
- /* EOS stuff */
-
- /* QoS stuff */
- /* Seek stuff */
- GST_EVENT_MINOR_OFFSET,
- GST_EVENT_MINOR_TIME,
-
- /* caps nego stuff */
- GST_EVENT_MINOR_CAPS_TRY,
- GST_EVENT_MINOR_CAPS_START,
- GST_EVENT_MINOR_CAPS_FINAL,
-} GstEventMinorType;
-
-
-Receiving events
-----------------
-
-a sample GstEventFunction, the event functions returns TRUE if the event is handled,
-FALSE otherwise.
-
-gboolean
-gst_anelement_handle_event (GstPad *pad, GstEvent *event)
-{
- if (event->type == GST_EVENT_EOS) {
- /* do something */
- return TRUE;
- }
- else if (event->type == GST_EVENT_CAPS) {
- if (event->minor == GST_EVENT_CAPS_TRY) {
- /* try using this caps structure */
- return TRUE; /* return FALSE to proxy ???*/
- }
- }
- return FALSE;
-}
-
-
-Default event handler for pads
-------------------------------
-
-gboolean
-gst_pad_handle_event (GstPad *pad, GstEvent *event)
-{
- GstElement *element;
- GList *pads;
- GstPad *srcpad;
- gboolean result = TRUE;
- GstPadDirection dir = GST_PAD_DIRECTION (pad);
-
- g_return_val_if_fail (pad != NULL, FALSE);
- g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
-
- element = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (pad)));
-
- /* send out the events to all pad with opposite direction */
- pads = gst_element_get_pad_list(element);
- while (pads) {
- otherpad = GST_PAD(pads->data);
- pads = g_list_next(pads);
-
- if (gst_pad_get_direction(otherpad) != dir) {
- result &= gst_pad_send_event (GST_REAL_PAD(otherpad), event);
- }
- }
-
- /* result is combined result of all handlers? */
- return result;
-}
-
-
diff --git a/docs/random/wtay/events2 b/docs/random/wtay/events2
new file mode 100644
index 0000000000..2e9b7c5a50
--- /dev/null
+++ b/docs/random/wtay/events2
@@ -0,0 +1,140 @@
+some random ramblings about the event system:
+
+Possible candidates for events
+------------------------------
+
+ - QoS
+ - EOS
+ - Seek
+ - caps nego??
+ - bufferpool get??
+ - ...
+
+Assumptions for events
+----------------------
+
+- They are tied to a pad.
+- get rid of gst_pad_set_*_function (except for the chain/get ones)
+- occur async to dataflow. (need locking?)
+- fixed set of events only for core features. (elements cannot abuse
+ events for doing dataflow)
+
+Questions
+---------
+
+limit the valid directions an event can travel in? ie. Can EOS only
+travel downstream (left to right)?
+
+eg. Seek travels upstream, but it makes sense to also make it travel
+ downstream (the case of a disksink, where we overwrite the header)
+
+
+Setting an event function
+-------------------------
+
+void gst_pad_set_event_function (GstPad *pad, gint event_mask,
+ GstEventFunction *function);
+
+
+event masks:
+
+typedef enum {
+ GST_EVENT_EOS = (1 << 0),
+ GST_EVENT_QOS = (1 << 1),
+ GST_EVENT_SEEK = (1 << 2),
+ GST_EVENT_CAPS = (1 << 3),
+} GstEventType;
+
+Event structure
+---------------
+
+typedef struct {
+ GstEventType type;
+ GstEventMinorType minor;
+ guint64 timestamp; /* also sequence number ?? */
+
+ union {
+ /* EOS stuff */
+ /* QoS stuff */
+ /* Seek stuff */
+ GstSeekType type; /* time, bytes, ... */
+ gint64 offset;
+ gint64 lenth;
+ /* Caps stuff */
+ GstCaps *caps;
+ } data;
+} GstEvent;
+
+
+typedef enum {
+ GST_EVENT_MINOR_NONE,
+ /* EOS stuff */
+
+ /* QoS stuff */
+ /* Seek stuff */
+ GST_EVENT_MINOR_OFFSET,
+ GST_EVENT_MINOR_TIME,
+
+ /* caps nego stuff */
+ GST_EVENT_MINOR_CAPS_TRY,
+ GST_EVENT_MINOR_CAPS_START,
+ GST_EVENT_MINOR_CAPS_FINAL,
+} GstEventMinorType;
+
+
+Receiving events
+----------------
+
+a sample GstEventFunction, the event functions returns TRUE if the event is handled,
+FALSE otherwise.
+
+gboolean
+gst_anelement_handle_event (GstPad *pad, GstEvent *event)
+{
+ if (event->type == GST_EVENT_EOS) {
+ /* do something */
+ return TRUE;
+ }
+ else if (event->type == GST_EVENT_CAPS) {
+ if (event->minor == GST_EVENT_CAPS_TRY) {
+ /* try using this caps structure */
+ return TRUE; /* return FALSE to proxy ???*/
+ }
+ }
+ return FALSE;
+}
+
+
+Default event handler for pads
+------------------------------
+
+gboolean
+gst_pad_handle_event (GstPad *pad, GstEvent *event)
+{
+ GstElement *element;
+ GList *pads;
+ GstPad *srcpad;
+ gboolean result = TRUE;
+ GstPadDirection dir = GST_PAD_DIRECTION (pad);
+
+ g_return_val_if_fail (pad != NULL, FALSE);
+ g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
+
+ element = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (pad)));
+
+ /* send out the events to all pad with opposite direction */
+ pads = gst_element_get_pad_list(element);
+ while (pads) {
+ otherpad = GST_PAD(pads->data);
+ pads = g_list_next(pads);
+
+ if (gst_pad_get_direction(otherpad) != dir) {
+ result &= gst_pad_send_event (GST_REAL_PAD(otherpad), event);
+ }
+ }
+
+ /* result is combined result of all handlers? */
+ return result;
+}
+
+
diff --git a/editor/gsteditorproject.c b/editor/gsteditorproject.c
index 867972de00..e21b563c29 100644
--- a/editor/gsteditorproject.c
+++ b/editor/gsteditorproject.c
@@ -120,6 +120,7 @@ gst_editor_project_new (void)
GstEditorProject *
gst_editor_project_new_from_file (const guchar *fname)
{
+#ifndef GST_DISABLE_LOADSAVE
GstEditorProject *editorproject;
GstXML *xml;
GList *elements;
@@ -140,8 +141,10 @@ gst_editor_project_new_from_file (const guchar *fname)
elements = g_list_next (elements);
}
-
return editorproject;
+#else
+ return NULL;
+#endif
}
void
@@ -162,7 +165,9 @@ gst_editor_project_save_as (GstEditorProject *project, const guchar *fname)
while (elements) {
GstElement *element = (GstElement *) elements->data;
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile (fname, gst_xml_write (element));
+#endif
elements = g_list_next (elements);
}
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 6fe9c9c70b..b81c1568f7 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -5,10 +5,16 @@ else
GNOME_SUBDS =
endif
-SUBDIRS = $(GNOME_SUBDS) \
+if GST_DISABLE_LOADSAVE
+GST_LOADSAVE_DIRS =
+else
+GST_LOADSAVE_DIRS = xml typefind
+endif
+
+SUBDIRS = $(GNOME_SUBDS) $(GST_LOADSAVE_DIRS) \
helloworld helloworld2 \
queue queue2 queue3 queue4 \
- launch thread xml plugins typefind mixer cutter
+ launch thread plugins mixer cutter
DIST_SUBDIRS = autoplug \
helloworld helloworld2 \
diff --git a/examples/autoplug/autoplug.c b/examples/autoplug/autoplug.c
index 550b182530..9de5ba56f2 100644
--- a/examples/autoplug/autoplug.c
+++ b/examples/autoplug/autoplug.c
@@ -94,7 +94,9 @@ gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline)
gst_element_set_state (pipeline, GST_STATE_PLAYING);
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("xmlTest.gst", gst_xml_write (GST_ELEMENT (pipeline)));
+#endif
}
gboolean
diff --git a/examples/mixer/mixer.c b/examples/mixer/mixer.c
index 0edbfa539f..7a02eddcb4 100644
--- a/examples/mixer/mixer.c
+++ b/examples/mixer/mixer.c
@@ -182,7 +182,9 @@ int main(int argc,char *argv[])
}
env_register_cp (channel_in->volenv, num_channels * 10.0 , 1.0 / num_channels); /* to end level */
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("mixer.xml", gst_xml_write(GST_ELEMENT(main_bin)));
+#endif
/* start playing */
gst_element_set_state(main_bin, GST_STATE_PLAYING);
@@ -356,7 +358,9 @@ create_input_channel (int id, char* location)
gst_element_get_pad (decoder, "src"), "src_00");
#endif
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile ("mixer.gst", gst_xml_write (new_element));
+#endif
gst_bin_add (GST_BIN(channel->pipe), channel->volenv);
gst_bin_add (GST_BIN (channel->pipe), new_element);
diff --git a/gst/Makefile.am b/gst/Makefile.am
index 640288224a..6e7583219a 100644
--- a/gst/Makefile.am
+++ b/gst/Makefile.am
@@ -8,6 +8,8 @@ else
GSTARCH_SRCS =
endif
+#GST_INSTRUMENT_FLAGS = -finstrument-functions -DGST_ENABLE_FUNC_INSTRUMENTATION
+
if USE_GLIB2
GST_OBJECT_MODEL_SRC = gstmarshal.c
GST_OBJECT_MODEL_HDR = gstmarshal.h
@@ -67,6 +69,7 @@ libgst_la_SOURCES = \
gstcpu.c \
gstelement.c \
gstelementfactory.c \
+ gstevent.c \
gstextratypes.c \
gstinfo.c \
gstpad.c \
@@ -154,6 +157,7 @@ libgstincludedir = $(includedir)/gst
libgstinclude_HEADERS = \
cothreads.h \
gst.h \
+ gstconfig.h \
$(GST_OBJECT_MODEL_HDR) \
gstobject.h \
gsttypes.h \
@@ -164,6 +168,7 @@ libgstinclude_HEADERS = \
gstcaps.h \
gstclock.h \
gstcpu.h \
+ gstdata.h \
gstelement.h \
gstevent.h \
gstextratypes.h \
@@ -203,6 +208,7 @@ CFLAGS = \
-Wnested-externs \
-Winline -Wno-unused
+CFLAGS = $(LIBGST_CFLAGS) -D_GNU_SOURCE -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\" -Wall
LIBS = $(LIBGST_LIBS)
LDFLAGS = ""
libgst_la_LDFLAGS = -version-info $(GST_LIBVERSION)
diff --git a/gst/autoplug/gstautoplugger.c b/gst/autoplug/gstautoplugger.c
index 68ed930915..6138ff3657 100644
--- a/gst/autoplug/gstautoplugger.c
+++ b/gst/autoplug/gstautoplugger.c
@@ -430,7 +430,7 @@ gst_autoplugger_cache_empty(GstElement *element, GstAutoplugger *autoplugger)
// try to PLAY the whole thing
gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING);
- xmlSaveFile("autoplugger.gst", gst_xml_write(GST_ELEMENT_SCHED(autoplugger)->parent));
+// xmlSaveFile("autoplugger.gst", gst_xml_write(GST_ELEMENT_SCHED(autoplugger)->parent));
GST_INFO(GST_CAT_AUTOPLUG, "autoplugger_cache_empty finished");
}
diff --git a/gst/elements/Makefile.am b/gst/elements/Makefile.am
index 61c5ad7c16..f50e4f75b4 100644
--- a/gst/elements/Makefile.am
+++ b/gst/elements/Makefile.am
@@ -8,6 +8,8 @@ else
GSTHTTPSRC=
endif
+#CFLAGS += -O2 -Wall -finstrument-functions -DGST_ENABLE_FUNC_INSTRUMENTATION
+
libgstelements_la_DEPENDENCIES = ../libgst.la
libgstelements_la_SOURCES = \
gstelements.c \
@@ -37,8 +39,10 @@ noinst_HEADERS = \
gstfdsink.h \
gstpipefilter.h \
gsttee.h \
- gstaggregator.h
-CFLAGS += -O2 -Wall
+ gstaggregator.h \
+ gstsinesrc.h
+
+CFLAGS += -O2 -Wall
LDFLAGS += -lm
libgstelements_la_LIBADD = $(GHTTP_LIBS)
diff --git a/gst/elements/gstaggregator.c b/gst/elements/gstaggregator.c
index eb6c3013d9..49ec28f167 100644
--- a/gst/elements/gstaggregator.c
+++ b/gst/elements/gstaggregator.c
@@ -76,7 +76,8 @@ gst_aggregator_sched_get_type (void)
static void gst_aggregator_class_init (GstAggregatorClass *klass);
static void gst_aggregator_init (GstAggregator *aggregator);
-static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp);
+static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp, const
+ gchar *unused);
static void gst_aggregator_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
@@ -150,7 +151,7 @@ gst_aggregator_init (GstAggregator *aggregator)
}
static GstPad*
-gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ)
+gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
{
gchar *name;
GstPad *sinkpad;
diff --git a/gst/elements/gstdisksrc.c b/gst/elements/gstdisksrc.c
index ab13968eb9..ffe1b352e1 100644
--- a/gst/elements/gstdisksrc.c
+++ b/gst/elements/gstdisksrc.c
@@ -64,8 +64,8 @@ static void gst_disksrc_set_property (GObject *object, guint prop_id,
static void gst_disksrc_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
-static GstBuffer * gst_disksrc_get (GstPad *pad);
-static GstBuffer * gst_disksrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len);
+static GstBuffer* gst_disksrc_get (GstPad *pad);
+static GstBufferPool* gst_disksrc_get_bufferpool (GstPad *pad);
static GstElementStateReturn
gst_disksrc_change_state (GstElement *element);
@@ -73,7 +73,7 @@ static GstElementStateReturn
static gboolean gst_disksrc_open_file (GstDiskSrc *src);
static void gst_disksrc_close_file (GstDiskSrc *src);
-static GstElementClass *parent_class = NULL;
+static GstElementClass* parent_class = NULL;
//static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 };
GType
@@ -133,8 +133,8 @@ gst_disksrc_init (GstDiskSrc *disksrc)
// GST_FLAG_SET (disksrc, GST_SRC_);
disksrc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
- gst_pad_set_get_function (disksrc->srcpad,gst_disksrc_get);
- gst_pad_set_getregion_function (disksrc->srcpad,gst_disksrc_get_region);
+ gst_pad_set_get_function (disksrc->srcpad, gst_disksrc_get);
+ gst_pad_set_bufferpool_function (disksrc->srcpad, gst_disksrc_get_bufferpool);
gst_element_add_pad (GST_ELEMENT (disksrc), disksrc->srcpad);
disksrc->filename = NULL;
@@ -220,6 +220,56 @@ gst_disksrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
}
}
+static GstBuffer*
+gst_disksrc_buffer_new (GstBufferPool *pool, gint64 location, gint size, gpointer user_data)
+{
+ GstDiskSrc *src;
+ GstBuffer *buf;
+
+ src = GST_DISKSRC (user_data);
+
+ buf = gst_buffer_new ();
+ g_return_val_if_fail (buf != NULL, NULL);
+
+ /* simply set the buffer to point to the correct region of the file */
+ GST_BUFFER_DATA (buf) = src->map + location;
+ GST_BUFFER_OFFSET (buf) = location;
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
+
+ if ((location + size) > src->size)
+ GST_BUFFER_SIZE (buf) = src->size - location;
+ else
+ GST_BUFFER_SIZE (buf) = size;
+
+ GST_DEBUG (0,"map %p, offset %ld (%p), size %d\n", src->map, src->curoffset,
+ src->map + src->curoffset, GST_BUFFER_SIZE (buf));
+
+ return buf;
+}
+
+static void
+gst_disksrc_buffer_free (GstBuffer *buf)
+{
+ // FIXME do something here
+}
+
+static GstBufferPool*
+gst_disksrc_get_bufferpool (GstPad *pad)
+{
+ GstDiskSrc *src;
+
+ src = GST_DISKSRC (gst_pad_get_parent (pad));
+
+ if (!src->bufferpool) {
+ src->bufferpool = gst_buffer_pool_new ();
+ gst_buffer_pool_set_buffer_new_function (src->bufferpool, gst_disksrc_buffer_new);
+ gst_buffer_pool_set_buffer_free_function (src->bufferpool, gst_disksrc_buffer_free);
+ gst_buffer_pool_set_user_data (src->bufferpool, src);
+ }
+
+ return src->bufferpool;
+}
+
/**
* gst_disksrc_get:
* @pad: #GstPad to push a buffer from
@@ -246,28 +296,10 @@ gst_disksrc_get (GstPad *pad)
return buf;
}
- /* create the buffer */
- // FIXME: should eventually use a bufferpool for this
- buf = gst_buffer_new ();
-
- g_return_val_if_fail (buf != NULL, NULL);
-
- /* simply set the buffer to point to the correct region of the file */
- GST_BUFFER_DATA (buf) = src->map + src->curoffset;
- GST_BUFFER_OFFSET (buf) = src->curoffset;
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
-
- if ((src->curoffset + src->bytes_per_read) > src->size) {
- GST_BUFFER_SIZE (buf) = src->size - src->curoffset;
- // FIXME: set the buffer's EOF bit here
- } else
- GST_BUFFER_SIZE (buf) = src->bytes_per_read;
-
- GST_DEBUG (0,"map %p, offset %ld (%p), size %d\n", src->map, src->curoffset,
- src->map + src->curoffset, GST_BUFFER_SIZE (buf));
+ // FIXME use a bufferpool
+ buf = gst_disksrc_buffer_new (NULL, src->curoffset, src->bytes_per_read, src);
//gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
-
src->curoffset += GST_BUFFER_SIZE (buf);
if (src->new_seek) {
@@ -280,61 +312,6 @@ gst_disksrc_get (GstPad *pad)
return buf;
}
-/**
- * gst_disksrc_get_region:
- * @src: #GstSrc to push a buffer from
- * @offset: offset in file
- * @size: number of bytes
- *
- * Push a new buffer from the disksrc of given size at given offset.
- */
-static GstBuffer *
-gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
-{
- GstDiskSrc *src;
- GstBuffer *buf;
-
- g_return_val_if_fail (pad != NULL, NULL);
- g_return_val_if_fail (type == GST_REGION_OFFSET_LEN, NULL);
-
- src = GST_DISKSRC (gst_pad_get_parent (pad));
-
- g_return_val_if_fail (GST_IS_DISKSRC (src), NULL);
- g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL);
-
- /* deal with EOF state */
- if (offset >= src->size) {
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- GST_DEBUG (0,"map offset %lld >= size %ld --> eos\n", offset, src->size);
- //FIXME
- buf = gst_buffer_new();
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_EOS);
- return buf;
- }
-
- /* create the buffer */
- // FIXME: should eventually use a bufferpool for this
- buf = gst_buffer_new ();
- g_return_val_if_fail (buf != NULL, NULL);
-
- /* simply set the buffer to point to the correct region of the file */
- GST_BUFFER_DATA (buf) = src->map + offset;
- GST_BUFFER_OFFSET (buf) = offset;
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
-
- if ((offset + len) > src->size) {
- GST_BUFFER_SIZE (buf) = src->size - offset;
- // FIXME: set the buffer's EOF bit here
- } else
- GST_BUFFER_SIZE (buf) = len;
-
- GST_DEBUG (0,"map %p, offset %lld, size %d\n", src->map, offset, GST_BUFFER_SIZE (buf));
-
- /* we're done, return the buffer off now */
- return buf;
-}
-
-
/* open the file and mmap it, necessary to go to READY state */
static gboolean
gst_disksrc_open_file (GstDiskSrc *src)
diff --git a/gst/elements/gstdisksrc.h b/gst/elements/gstdisksrc.h
index 155a362c2d..4591254734 100644
--- a/gst/elements/gstdisksrc.h
+++ b/gst/elements/gstdisksrc.h
@@ -64,6 +64,7 @@ struct _GstDiskSrc {
gchar *filename;
/* fd */
gint fd;
+ GstBufferPool *bufferpool;
/* mapping parameters */
gulong size; /* how long is the file? */
diff --git a/gst/elements/gstfakesink.c b/gst/elements/gstfakesink.c
index 11eac007d1..02eb921fa3 100644
--- a/gst/elements/gstfakesink.c
+++ b/gst/elements/gstfakesink.c
@@ -45,6 +45,7 @@ enum {
ARG_0,
ARG_NUM_SINKS,
ARG_SILENT,
+ ARG_DUMP,
};
GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
@@ -58,7 +59,8 @@ GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
static void gst_fakesink_class_init (GstFakeSinkClass *klass);
static void gst_fakesink_init (GstFakeSink *fakesink);
-static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ);
+static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const
+ gchar *unused);
static void gst_fakesink_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
@@ -66,7 +68,6 @@ static void gst_fakesink_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static void gst_fakesink_chain (GstPad *pad, GstBuffer *buf);
-static gboolean gst_fakesink_event (GstPad *pad, GstEventType event, guint64 timestamp, guint32 data);
static GstElementClass *parent_class = NULL;
static guint gst_fakesink_signals[LAST_SIGNAL] = { 0 };
@@ -109,6 +110,9 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
g_param_spec_boolean ("silent", "silent", "silent",
FALSE, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
+ g_param_spec_boolean ("dump", "dump", "dump",
+ FALSE, G_PARAM_READWRITE));
gst_fakesink_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
@@ -129,15 +133,15 @@ gst_fakesink_init (GstFakeSink *fakesink)
pad = gst_pad_new ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (fakesink), pad);
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
- gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_event));
fakesink->sinkpads = g_slist_prepend (NULL, pad);
fakesink->numsinkpads = 1;
fakesink->silent = FALSE;
+ fakesink->dump = FALSE;
}
static GstPad*
-gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ)
+gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
{
gchar *name;
GstPad *sinkpad;
@@ -175,6 +179,9 @@ gst_fakesink_set_property (GObject *object, guint prop_id, const GValue *value,
case ARG_SILENT:
sink->silent = g_value_get_boolean (value);
break;
+ case ARG_DUMP:
+ sink->dump = g_value_get_boolean (value);
+ break;
default:
break;
}
@@ -197,6 +204,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
case ARG_SILENT:
g_value_set_boolean (value, sink->silent);
break;
+ case ARG_DUMP:
+ g_value_set_boolean (value, sink->dump);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -206,9 +216,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
/**
* gst_fakesink_chain:
* @pad: the pad this faksink is connected to
- * @buf: the buffer that has to be absorbed
+ * @buffer: the buffer or event that has to be absorbed
*
- * take the buffer from the pad and unref it without doing
+ * Take the buffer or event from the pad and unref it without doing
* anything with it.
*/
static void
@@ -221,12 +231,33 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
g_return_if_fail (buf != NULL);
fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
+
+ if (GST_IS_EVENT(buf)) {
+ GstEvent *event = GST_EVENT (buf);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ g_print("fakesink: have EOS event!\n");
+ gst_element_set_state (GST_ELEMENT (fakesink), GST_STATE_PAUSED);
+ break;
+ default:
+ g_print("fakesink: have unhandled event!\n");
+ break;
+ }
+ gst_event_free (event);
+ return;
+ }
+
if (!fakesink->silent)
- g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) \n",
- GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
-
- g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0,
- buf);
+ g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) %p\n",
+ GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
+
+ g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
+
+ if (fakesink->dump)
+ {
+ gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ }
gst_buffer_unref (buf);
}
@@ -238,14 +269,3 @@ gst_fakesink_factory_init (GstElementFactory *factory)
return TRUE;
}
-
-
-
-static gboolean
-gst_fakesink_event (GstPad *pad, GstEventType event, guint64 timestamp, guint32 data)
-{
- GST_DEBUG (GST_CAT_EVENT, "fakesink has event %d on pad %s:%s\n",event,GST_DEBUG_PAD_NAME(pad));
- if (event == GST_EVENT_EOS) {
- GST_DEBUG(GST_CAT_EVENT, "have EOS\n");
- }
-}
diff --git a/gst/elements/gstfakesink.h b/gst/elements/gstfakesink.h
index cafc18b87c..85aa9fbdb7 100644
--- a/gst/elements/gstfakesink.h
+++ b/gst/elements/gstfakesink.h
@@ -57,6 +57,7 @@ struct _GstFakeSink {
GSList *sinkpads;
gint numsinkpads;
gboolean silent;
+ gboolean dump;
};
struct _GstFakeSinkClass {
diff --git a/gst/elements/gstfakesrc.c b/gst/elements/gstfakesrc.c
index d946529434..bed56e486f 100644
--- a/gst/elements/gstfakesrc.c
+++ b/gst/elements/gstfakesrc.c
@@ -21,6 +21,9 @@
*/
+#include
+#include
+
#include
@@ -47,10 +50,17 @@ enum {
ARG_NUM_SOURCES,
ARG_LOOP_BASED,
ARG_OUTPUT,
+ ARG_DATA,
+ ARG_SIZETYPE,
+ ARG_SIZEMIN,
+ ARG_SIZEMAX,
+ ARG_FILLTYPE,
ARG_PATTERN,
ARG_NUM_BUFFERS,
ARG_EOS,
- ARG_SILENT
+ ARG_SILENT,
+ ARG_DUMP,
+ ARG_PARENTSIZE
};
GST_PADTEMPLATE_FACTORY (fakesrc_src_factory,
@@ -82,12 +92,69 @@ gst_fakesrc_output_get_type (void)
return fakesrc_output_type;
}
+#define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type())
+static GType
+gst_fakesrc_data_get_type (void)
+{
+ static GType fakesrc_data_type = 0;
+ static GEnumValue fakesrc_data[] = {
+ { FAKESRC_DATA_ALLOCATE, "2", "Allocate data"},
+ { FAKESRC_DATA_SUBBUFFER, "3", "Subbuffer data"},
+ {0, NULL, NULL},
+ };
+ if (!fakesrc_data_type) {
+ fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data);
+ }
+ return fakesrc_data_type;
+}
+
+#define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
+static GType
+gst_fakesrc_sizetype_get_type (void)
+{
+ static GType fakesrc_sizetype_type = 0;
+ static GEnumValue fakesrc_sizetype[] = {
+ { FAKESRC_SIZETYPE_NULL, "1", "Send empty buffers"},
+ { FAKESRC_SIZETYPE_FIXED, "2", "Fixed size buffers (sizemax sized)"},
+ { FAKESRC_SIZETYPE_RANDOM, "3", "Random sized buffers (sizemin <= size <= sizemax)"},
+ {0, NULL, NULL},
+ };
+ if (!fakesrc_sizetype_type) {
+ fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
+ }
+ return fakesrc_sizetype_type;
+}
+
+#define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
+static GType
+gst_fakesrc_filltype_get_type (void)
+{
+ static GType fakesrc_filltype_type = 0;
+ static GEnumValue fakesrc_filltype[] = {
+ { FAKESRC_FILLTYPE_NOTHING, "1", "Leave data as malloced"},
+ { FAKESRC_FILLTYPE_NULL, "2", "Fill buffers with zeros"},
+ { FAKESRC_FILLTYPE_RANDOM, "3", "Fill buffers with random crap"},
+ { FAKESRC_FILLTYPE_PATTERN, "4", "Fill buffers with pattern 0x00 -> 0xff"},
+ { FAKESRC_FILLTYPE_PATTERN_CONT, "5", "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
+ {0, NULL, NULL},
+ };
+ if (!fakesrc_filltype_type) {
+ fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
+ }
+ return fakesrc_filltype_type;
+}
+
static void gst_fakesrc_class_init (GstFakeSrcClass *klass);
static void gst_fakesrc_init (GstFakeSrc *fakesrc);
static GstPad* gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ);
-static void gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static void gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static void gst_fakesrc_update_functions (GstFakeSrc *src);
+static void gst_fakesrc_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void gst_fakesrc_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
+static GstElementStateReturn gst_fakesrc_change_state (GstElement *element);
static GstBuffer* gst_fakesrc_get (GstPad *pad);
static void gst_fakesrc_loop (GstElement *element);
@@ -137,6 +204,24 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT,
g_param_spec_enum("output","output","output",
GST_TYPE_FAKESRC_OUTPUT,FAKESRC_FIRST_LAST_LOOP,G_PARAM_READWRITE)); // CHECKME!
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
+ g_param_spec_enum ("data", "data", "data",
+ GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
+ g_param_spec_enum ("sizetype", "sizetype", "sizetype",
+ GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
+ g_param_spec_int ("sizemin","sizemin","sizemin",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
+ g_param_spec_int ("sizemax","sizemax","sizemax",
+ 0, G_MAXINT, 4096, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
+ g_param_spec_int ("parentsize","parentsize","parentsize",
+ 0, G_MAXINT, 4096 * 10, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
+ g_param_spec_enum ("filltype", "filltype", "filltype",
+ GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PATTERN,
g_param_spec_string("pattern","pattern","pattern",
NULL, G_PARAM_READWRITE)); // CHECKME
@@ -149,6 +234,9 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SILENT,
g_param_spec_boolean("silent","silent","silent",
FALSE, G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
+ g_param_spec_boolean ("dump","dump","dump",
+ FALSE, G_PARAM_READWRITE));
gst_fakesrc_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
@@ -159,7 +247,8 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
- gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
+ gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
+ gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
}
static void
@@ -176,17 +265,21 @@ gst_fakesrc_init (GstFakeSrc *fakesrc)
fakesrc->srcpads = g_slist_append (NULL, pad);
fakesrc->loop_based = FALSE;
-
- if (fakesrc->loop_based)
- gst_element_set_loop_function (GST_ELEMENT (fakesrc), GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
- else
- gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
+ gst_fakesrc_update_functions (fakesrc);
fakesrc->num_buffers = -1;
fakesrc->buffer_count = 0;
fakesrc->silent = FALSE;
- // we're ready right away, since we don't have any args...
-// gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_READY);
+ fakesrc->dump = FALSE;
+ fakesrc->pattern_byte = 0x00;
+ fakesrc->need_flush = FALSE;
+ fakesrc->data = FAKESRC_DATA_ALLOCATE;
+ fakesrc->sizetype = FAKESRC_SIZETYPE_NULL;
+ fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING;
+ fakesrc->sizemin = 0;
+ fakesrc->sizemax = 4096;
+ fakesrc->parent = NULL;
+ fakesrc->parentsize = 4096 * 10;
}
static GstPad*
@@ -216,6 +309,34 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
return srcpad;
}
+static gboolean
+gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
+{
+ GstFakeSrc *src;
+
+ src = GST_FAKESRC (gst_pad_get_parent (pad));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_SEEK:
+ g_print("fakesrc: have seek event\n");
+ src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
+ if (!GST_EVENT_SEEK_FLUSH (event)) {
+ gst_event_free (event);
+ break;
+ }
+ // else we do a flush too
+ case GST_EVENT_FLUSH:
+ g_print("fakesrc: have flush event\n");
+ src->need_flush = TRUE;
+ break;
+ default:
+ g_print("fakesrc: have unhandled event\n");
+ break;
+ }
+
+ return TRUE;
+}
+
static void
gst_fakesrc_update_functions (GstFakeSrc *src)
{
@@ -238,10 +359,25 @@ gst_fakesrc_update_functions (GstFakeSrc *src)
else {
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
}
+
+ gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
pads = g_slist_next (pads);
}
}
+static void
+gst_fakesrc_alloc_parent (GstFakeSrc *src)
+{
+ GstBuffer *buf;
+
+ buf = gst_buffer_new ();
+ GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
+ GST_BUFFER_SIZE (buf) = src->parentsize;
+
+ src->parent = buf;
+ src->parentoffset = 0;
+}
+
static void
gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
@@ -257,6 +393,37 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
break;
case ARG_OUTPUT:
break;
+ case ARG_DATA:
+ src->data = g_value_get_int (value);
+ switch (src->data) {
+ case FAKESRC_DATA_ALLOCATE:
+ if (src->parent) {
+ gst_buffer_unref (src->parent);
+ src->parent = NULL;
+ }
+ break;
+ case FAKESRC_DATA_SUBBUFFER:
+ if (!src->parent)
+ gst_fakesrc_alloc_parent (src);
+ default:
+ break;
+ }
+ break;
+ case ARG_SIZETYPE:
+ src->sizetype = g_value_get_int (value);
+ break;
+ case ARG_SIZEMIN:
+ src->sizemin = g_value_get_int (value);
+ break;
+ case ARG_SIZEMAX:
+ src->sizemax = g_value_get_int (value);
+ break;
+ case ARG_PARENTSIZE:
+ src->parentsize = g_value_get_int (value);
+ break;
+ case ARG_FILLTYPE:
+ src->filltype = g_value_get_int (value);
+ break;
case ARG_PATTERN:
break;
case ARG_NUM_BUFFERS:
@@ -269,6 +436,9 @@ GST_INFO (0, "will EOS on next buffer");
case ARG_SILENT:
src->silent = g_value_get_boolean (value);
break;
+ case ARG_DUMP:
+ src->dump = g_value_get_boolean (value);
+ break;
default:
break;
}
@@ -294,6 +464,24 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
case ARG_OUTPUT:
g_value_set_int (value, src->output);
break;
+ case ARG_DATA:
+ g_value_set_int (value, src->data);
+ break;
+ case ARG_SIZETYPE:
+ g_value_set_int (value, src->sizetype);
+ break;
+ case ARG_SIZEMIN:
+ g_value_set_int (value, src->sizemin);
+ break;
+ case ARG_SIZEMAX:
+ g_value_set_int (value, src->sizemax);
+ break;
+ case ARG_PARENTSIZE:
+ g_value_set_int (value, src->parentsize);
+ break;
+ case ARG_FILLTYPE:
+ g_value_set_int (value, src->filltype);
+ break;
case ARG_PATTERN:
g_value_set_string (value, src->pattern);
break;
@@ -306,21 +494,150 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
case ARG_SILENT:
g_value_set_boolean (value, src->silent);
break;
+ case ARG_DUMP:
+ g_value_set_boolean (value, src->dump);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
+static void
+gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
+{
+ if (GST_BUFFER_SIZE (buf) == 0)
+ return;
+
+ switch (src->filltype) {
+ case FAKESRC_FILLTYPE_NULL:
+ memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
+ break;
+ case FAKESRC_FILLTYPE_RANDOM:
+ {
+ gint i;
+ guint8 *ptr = GST_BUFFER_DATA (buf);
+
+ for (i = GST_BUFFER_SIZE (buf); i; i--) {
+ *ptr++ = (gint8)((255.0)*rand()/(RAND_MAX));
+ }
+ break;
+ }
+ case FAKESRC_FILLTYPE_PATTERN:
+ src->pattern_byte = 0x00;
+ case FAKESRC_FILLTYPE_PATTERN_CONT:
+ {
+ gint i;
+ guint8 *ptr = GST_BUFFER_DATA (buf);
+
+ for (i = GST_BUFFER_SIZE (buf); i; i--) {
+ *ptr++ = src->pattern_byte++;
+ }
+ break;
+ }
+ case FAKESRC_FILLTYPE_NOTHING:
+ default:
+ break;
+ }
+}
+
+static GstBuffer*
+gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
+{
+ GstBuffer *buf;
+
+ buf = gst_buffer_new ();
+ GST_BUFFER_SIZE(buf) = size;
+
+ if (size != 0) {
+ switch (src->filltype) {
+ case FAKESRC_FILLTYPE_NOTHING:
+ GST_BUFFER_DATA(buf) = g_malloc (size);
+ break;
+ case FAKESRC_FILLTYPE_NULL:
+ GST_BUFFER_DATA(buf) = g_malloc0 (size);
+ break;
+ case FAKESRC_FILLTYPE_RANDOM:
+ case FAKESRC_FILLTYPE_PATTERN:
+ case FAKESRC_FILLTYPE_PATTERN_CONT:
+ default:
+ GST_BUFFER_DATA(buf) = g_malloc (size);
+ gst_fakesrc_prepare_buffer (src, buf);
+ break;
+ }
+ }
+
+ return buf;
+}
+
+static guint
+gst_fakesrc_get_size (GstFakeSrc *src)
+{
+ guint size;
+
+ switch (src->sizetype) {
+ case FAKESRC_SIZETYPE_FIXED:
+ size = src->sizemax;
+ break;
+ case FAKESRC_SIZETYPE_RANDOM:
+ size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin));
+ break;
+ case FAKESRC_SIZETYPE_NULL:
+ default:
+ size = 0;
+ break;
+ }
+
+ return size;
+}
+
+static GstBuffer *
+gst_fakesrc_create_buffer (GstFakeSrc *src)
+{
+ GstBuffer *buf;
+ guint size;
+ gboolean dump = src->dump;
+
+ size = gst_fakesrc_get_size (src);
+ if (size == 0)
+ return gst_buffer_new();
+
+ switch (src->data) {
+ case FAKESRC_DATA_ALLOCATE:
+ buf = gst_fakesrc_alloc_buffer (src, size);
+ break;
+ case FAKESRC_DATA_SUBBUFFER:
+ // see if we have a parent to subbuffer
+ if (!src->parent) {
+ gst_fakesrc_alloc_parent (src);
+ g_assert (src->parent);
+ }
+ // see if it's large enough
+ if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
+ buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
+ src->parentoffset += size;
+ }
+ else {
+ // the parent is useless now
+ gst_buffer_unref (src->parent);
+ src->parent = NULL;
+ // try again (this will allocate a new parent)
+ return gst_fakesrc_create_buffer (src);
+ }
+ gst_fakesrc_prepare_buffer (src, buf);
+ break;
+ default:
+ g_warning ("fakesrc: dunno how to allocate buffers !");
+ buf = gst_buffer_new();
+ break;
+ }
+ if (dump) {
+ gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ }
+
+ return buf;
+}
-/**
- * gst_fakesrc_get:
- * @src: the faksesrc to get
- *
- * generate an empty buffer and return it
- *
- * Returns: a new empty buffer
- */
static GstBuffer *
gst_fakesrc_get(GstPad *pad)
{
@@ -333,9 +650,16 @@ gst_fakesrc_get(GstPad *pad)
g_return_val_if_fail (GST_IS_FAKESRC (src), NULL);
+ if (src->need_flush) {
+ src->need_flush = FALSE;
+ g_print("fakesrc: sending FLUSH\n");
+ return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
+ }
+
if (src->num_buffers == 0) {
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- return NULL;
+ g_print("fakesrc: sending EOS\n");
+ gst_element_set_state (GST_ELEMENT (src), GST_STATE_PAUSED);
+ return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
}
else {
if (src->num_buffers > 0)
@@ -344,11 +668,11 @@ gst_fakesrc_get(GstPad *pad)
if (src->eos) {
GST_INFO (0, "fakesrc is setting eos on pad");
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- return NULL;
+ g_print("fakesrc: sending EOS\n");
+ return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
}
- buf = gst_buffer_new();
+ buf = gst_fakesrc_create_buffer (src);
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
if (!src->silent)
@@ -356,7 +680,7 @@ gst_fakesrc_get(GstPad *pad)
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
- buf);
+ buf, pad);
return buf;
}
@@ -387,21 +711,20 @@ gst_fakesrc_loop(GstElement *element)
GstBuffer *buf;
if (src->num_buffers == 0) {
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- return;
+ src->eos = TRUE;
}
else {
- if (src->num_buffers > 0)
- src->num_buffers--;
+ if (src->num_buffers > 0)
+ src->num_buffers--;
}
if (src->eos) {
GST_INFO (0, "fakesrc is setting eos on pad");
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- return;
+ gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
+ return;
}
- buf = gst_buffer_new();
+ buf = gst_fakesrc_create_buffer (src);
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
if (!src->silent)
@@ -409,7 +732,7 @@ gst_fakesrc_loop(GstElement *element)
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
- buf);
+ buf, pad);
gst_pad_push (pad, buf);
pads = g_slist_next (pads);
@@ -417,6 +740,31 @@ gst_fakesrc_loop(GstElement *element)
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
}
+static GstElementStateReturn
+gst_fakesrc_change_state (GstElement *element)
+{
+ GstFakeSrc *fakesrc;
+
+ g_return_val_if_fail (GST_IS_FAKESRC (element), GST_STATE_FAILURE);
+
+ fakesrc = GST_FAKESRC (element);
+
+ if (GST_STATE_PENDING (element) == GST_STATE_READY) {
+ fakesrc->buffer_count = 0;
+ fakesrc->pattern_byte = 0x00;
+ fakesrc->need_flush = FALSE;
+ if (fakesrc->parent) {
+ gst_buffer_unref (fakesrc->parent);
+ fakesrc->parent = NULL;
+ }
+ }
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+ return GST_STATE_SUCCESS;
+}
+
gboolean
gst_fakesrc_factory_init (GstElementFactory *factory)
{
diff --git a/gst/elements/gstfakesrc.h b/gst/elements/gstfakesrc.h
index ce5c2a9439..550015b2af 100644
--- a/gst/elements/gstfakesrc.h
+++ b/gst/elements/gstfakesrc.h
@@ -47,6 +47,25 @@ typedef enum {
FAKESRC_GET_ALWAYS_SUCEEDS,
} GstFakeSrcOutputType;
+typedef enum {
+ FAKESRC_DATA_ALLOCATE = 1,
+ FAKESRC_DATA_SUBBUFFER,
+} GstFakeSrcDataType;
+
+typedef enum {
+ FAKESRC_SIZETYPE_NULL = 1,
+ FAKESRC_SIZETYPE_FIXED,
+ FAKESRC_SIZETYPE_RANDOM
+} GstFakeSrcSizeType;
+
+typedef enum {
+ FAKESRC_FILLTYPE_NOTHING = 1,
+ FAKESRC_FILLTYPE_NULL,
+ FAKESRC_FILLTYPE_RANDOM,
+ FAKESRC_FILLTYPE_PATTERN,
+ FAKESRC_FILLTYPE_PATTERN_CONT
+} GstFakeSrcFillType;
+
#define GST_TYPE_FAKESRC \
(gst_fakesrc_get_type())
#define GST_FAKESRC(obj) \
@@ -64,16 +83,29 @@ typedef struct _GstFakeSrcClass GstFakeSrcClass;
struct _GstFakeSrc {
GstElement element;
- gboolean loop_based;
- gboolean eos;
- gint numsrcpads;
- GSList *srcpads;
+ gboolean loop_based;
+ gboolean eos;
+ gint numsrcpads;
+ GSList *srcpads;
+
GstFakeSrcOutputType output;
- gchar *pattern;
- GList *patternlist;
- gint num_buffers;
- guint64 buffer_count;
- gboolean silent;
+ GstFakeSrcDataType data;
+ GstFakeSrcSizeType sizetype;
+ GstFakeSrcFillType filltype;
+
+ guint sizemin;
+ guint sizemax;
+ GstBuffer *parent;
+ guint parentsize;
+ guint parentoffset;
+ guint8 pattern_byte;
+ gchar *pattern;
+ GList *patternlist;
+ gint num_buffers;
+ guint64 buffer_count;
+ gboolean silent;
+ gboolean dump;
+ gboolean need_flush;
};
struct _GstFakeSrcClass {
diff --git a/gst/elements/gstfilesrc.c b/gst/elements/gstfilesrc.c
index 36214941e1..f53548f328 100644
--- a/gst/elements/gstfilesrc.c
+++ b/gst/elements/gstfilesrc.c
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
/**********************************************************************
@@ -74,6 +75,9 @@ GstElementDetails gst_filesrc_details = {
"(C) 1999",
};
+//#define fs_print(format,args...) g_print(format, ## args)
+#define fs_print(format,args...)
+
#define GST_TYPE_FILESRC \
(gst_filesrc_get_type())
@@ -110,10 +114,12 @@ struct _GstFileSrc {
gboolean touch; // whether to touch every page
GstBuffer *mapbuf;
- off_t mapsize;
+ size_t mapsize;
GTree *map_regions;
GMutex *map_regions_lock;
+
+ gboolean seek_happened;
};
struct _GstFileSrcClass {
@@ -135,6 +141,7 @@ enum {
ARG_BLOCKSIZE,
ARG_OFFSET,
ARG_MAPSIZE,
+ ARG_TOUCH,
};
@@ -203,6 +210,9 @@ gst_filesrc_class_init (GstFileSrcClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MAPSIZE,
g_param_spec_ulong("mmapsize","mmap() Block Size","Size in bytes of mmap()d regions",
0,G_MAXULONG,4*1048576,G_PARAM_READWRITE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TOUCH,
+ g_param_spec_boolean("touch","Touch read data","Touch data to force disk read before push()",
+ TRUE,G_PARAM_READWRITE));
gobject_class->set_property = gst_filesrc_set_property;
gobject_class->get_property = gst_filesrc_get_property;
@@ -246,6 +256,8 @@ gst_filesrc_init (GstFileSrc *src)
src->map_regions = g_tree_new(gst_filesrc_bufcmp);
src->map_regions_lock = g_mutex_new();
+
+ src->seek_happened = FALSE;
}
@@ -286,6 +298,9 @@ gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
else
GST_INFO(0, "invalid mapsize, must a multiple of pagesize, which is %d\n",src->pagesize);
break;
+ case ARG_TOUCH:
+ src->touch = g_value_get_boolean (value);
+ break;
default:
break;
}
@@ -320,6 +335,9 @@ gst_filesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
case ARG_MAPSIZE:
g_value_set_ulong (value, src->mapsize);
break;
+ case ARG_TOUCH:
+ g_value_set_boolean (value, src->touch);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -331,7 +349,7 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
{
GstFileSrc *src = GST_FILESRC(GST_BUFFER_POOL_PRIVATE(buf));
- // fprintf(stderr,"freeing mmap()d buffer at %d+%d\n",GST_BUFFER_OFFSET(buf),GST_BUFFER_SIZE(buf));
+ fs_print ("freeing mmap()d buffer at %d+%d\n",GST_BUFFER_OFFSET(buf),GST_BUFFER_SIZE(buf));
// remove the buffer from the list of available mmap'd regions
g_mutex_lock(src->map_regions_lock);
@@ -347,21 +365,24 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
}
static GstBuffer *
-gst_filesrc_map_region (GstFileSrc *src, off_t offset, off_t size)
+gst_filesrc_map_region (GstFileSrc *src, off_t offset, size_t size)
{
GstBuffer *buf;
gint retval;
-// fprintf(stderr,"mapping region %d+%d from file into memory\n",offset,size);
+ g_return_val_if_fail (offset >= 0, NULL);
+
+ fs_print ("mapping region %08lx+%08lx from file into memory\n",offset,size);
// time to allocate a new mapbuf
buf = gst_buffer_new();
// mmap() the data into this new buffer
GST_BUFFER_DATA(buf) = mmap (NULL, size, PROT_READ, MAP_SHARED, src->fd, offset);
if (GST_BUFFER_DATA(buf) == NULL) {
- fprintf(stderr, "ERROR: gstfilesrc couldn't map file!\n");
- } else if (GST_BUFFER_DATA(buf) == (void *)-1) {
- perror("gstfilesrc:mmap()");
+ fprintf (stderr, "ERROR: gstfilesrc couldn't map file!\n");
+ } else if (GST_BUFFER_DATA(buf) == MAP_FAILED) {
+ g_error ("gstfilesrc mmap(0x%x, %d, 0x%llx) : %s",
+ size, src->fd, offset, sys_errlist[errno]);
}
// madvise to tell the kernel what to do with it
retval = madvise(GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf),MADV_SEQUENTIAL);
@@ -382,20 +403,27 @@ gst_filesrc_map_region (GstFileSrc *src, off_t offset, off_t size)
}
static GstBuffer *
-gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, off_t size)
+gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, size_t size)
{
- int mod, mapbase, mapsize;
+ size_t mapsize;
+ off_t mod, mapbase;
GstBuffer *map;
// printf("attempting to map a small buffer at %d+%d\n",offset,size);
// if the offset starts at a non-page boundary, we have to special case
if ((mod = offset % src->pagesize)) {
+ GstBuffer *ret;
+
mapbase = offset - mod;
mapsize = ((size + mod + src->pagesize - 1) / src->pagesize) * src->pagesize;
// printf("not on page boundaries, resizing map to %d+%d\n",mapbase,mapsize);
map = gst_filesrc_map_region(src, mapbase, mapsize);
- return gst_buffer_create_sub (map, offset - mapbase, size);
+ ret = gst_buffer_create_sub (map, offset - mapbase, size);
+
+ gst_buffer_unref (map);
+
+ return ret;
}
return gst_filesrc_map_region(src,offset,size);
@@ -431,8 +459,8 @@ gst_filesrc_get (GstPad *pad)
{
GstFileSrc *src;
GstBuffer *buf = NULL, *map;
- off_t readend,readsize,mapstart,mapend;
- gboolean eof = FALSE;
+ size_t readsize;
+ off_t readend,mapstart,mapend;
GstFileSrcRegion region;
int i;
@@ -440,6 +468,18 @@ gst_filesrc_get (GstPad *pad)
src = GST_FILESRC (gst_pad_get_parent (pad));
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN), NULL);
+ // check for seek
+ if (src->seek_happened) {
+ src->seek_happened = FALSE;
+ return gst_event_new(GST_EVENT_DISCONTINUOUS);
+ }
+
+ // check for EOF
+ if (src->curoffset == src->filelen) {
+ gst_element_set_state(src,GST_STATE_PAUSED);
+ return gst_event_new(GST_EVENT_EOS);
+ }
+
// calculate end pointers so we don't have to do so repeatedly later
readsize = src->block_size;
readend = src->curoffset + src->block_size; // note this is the byte *after* the read
@@ -450,7 +490,6 @@ gst_filesrc_get (GstPad *pad)
if (readend > src->filelen) {
readsize = src->filelen - src->curoffset;
readend = src->curoffset;
- eof = TRUE;
}
// if the start is past the mapstart
@@ -458,15 +497,15 @@ gst_filesrc_get (GstPad *pad)
// if the end is before the mapend, the buffer is in current mmap region...
// ('cause by definition if readend is in the buffer, so's readstart)
if (readend <= mapend) {
-// printf("read buf %d+%d lives in current mapbuf %d+%d, creating subbuffer of mapbuf\n",
-// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
+ fs_print ("read buf %d+%d lives in current mapbuf %d+%d, creating subbuffer of mapbuf\n",
+ src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
buf = gst_buffer_create_sub (src->mapbuf, src->curoffset - GST_BUFFER_OFFSET(src->mapbuf),
readsize);
// if the start actually is within the current mmap region, map an overlap buffer
} else if (src->curoffset < mapend) {
-// printf("read buf %d+%d starts in mapbuf %d+%d but ends outside, creating new mmap\n",
-// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
+ fs_print ("read buf %d+%d starts in mapbuf %d+%d but ends outside, creating new mmap\n",
+ src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
}
@@ -478,37 +517,39 @@ gst_filesrc_get (GstPad *pad)
// either the read buffer overlaps the start of the mmap region
// or the read buffer fully contains the current mmap region
// either way, it's really not relevant, we just create a new region anyway
-// printf("read buf %d+%d starts before mapbuf %d+%d, but overlaps it\n",
-// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
+ fs_print ("read buf %d+%d starts before mapbuf %d+%d, but overlaps it\n",
+ src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
}
// then deal with the case where the read buffer is totally outside
if (buf == NULL) {
// first check to see if there's a map that covers the right region already
-// printf("searching for mapbuf to cover %d+%d\n",src->curoffset,readsize);
+ fs_print ("searching for mapbuf to cover %d+%d\n",src->curoffset,readsize);
region.offset = src->curoffset;
region.size = readsize;
- map = g_tree_search(src->map_regions,gst_filesrc_search_region_match,®ion);
+ map = g_tree_search (src->map_regions,
+ (GCompareFunc) gst_filesrc_search_region_match,
+ ®ion);
// if we found an exact match, subbuffer it
if (map != NULL) {
-// printf("found mapbuf at %d+%d, creating subbuffer\n",GST_BUFFER_OFFSET(map),GST_BUFFER_SIZE(map));
+ fs_print ("found mapbuf at %d+%d, creating subbuffer\n",GST_BUFFER_OFFSET(map),GST_BUFFER_SIZE(map));
buf = gst_buffer_create_sub (map, src->curoffset - GST_BUFFER_OFFSET(map), readsize);
// otherwise we need to create something out of thin air
} else {
// if the read buffer crosses a mmap region boundary, create a one-off region
if ((src->curoffset / src->mapsize) != (readend / src->mapsize)) {
-// printf("read buf %d+%d crosses a %d-byte boundary, creating a one-off\n",
-// src->curoffset,readsize,src->mapsize);
+ fs_print ("read buf %d+%d crosses a %d-byte boundary, creating a one-off\n",
+ src->curoffset,readsize,src->mapsize);
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
// otherwise we will create a new mmap region and set it to the default
} else {
off_t nextmap = src->curoffset - (src->curoffset % src->mapsize);
-// printf("read buf %d+%d in new mapbuf at %d+%d, mapping and subbuffering\n",
-// src->curoffset,readsize,nextmap,src->mapsize);
+ fs_print ("read buf %d+%d in new mapbuf at %d+%d, mapping and subbuffering\n",
+ src->curoffset,readsize,nextmap,src->mapsize);
// first, we're done with the old mapbuf
gst_buffer_unref(src->mapbuf);
// create a new one
@@ -525,8 +566,6 @@ gst_filesrc_get (GstPad *pad)
*(GST_BUFFER_DATA(buf)+i) = *(GST_BUFFER_DATA(buf)+i);
}
- // if we hit EOF,
-
/* we're done, return the buffer */
src->curoffset += GST_BUFFER_SIZE(buf);
return buf;
@@ -567,6 +606,7 @@ gst_filesrc_close_file (GstFileSrc *src)
{
g_return_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN));
+ g_print ("close\n");
/* close the file */
close (src->fd);
@@ -613,6 +653,7 @@ gst_filesrc_srcpad_event(GstPad *pad, GstEventType event, gint64 location, guint
} else if (data == SEEK_END) {
src->curoffset = src->filelen - (guint64)location;
}
+ src->seek_happened = TRUE;
// push a discontinuous event?
return TRUE;
}
diff --git a/gst/elements/gstsinesrc.c b/gst/elements/gstsinesrc.c
new file mode 100644
index 0000000000..75ca6ba3b9
--- /dev/null
+++ b/gst/elements/gstsinesrc.c
@@ -0,0 +1,452 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ * 2001 Steve Baker
+ *
+ * gstsinesrc.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include
+#include
+#include
+
+#include
+
+
+GstElementDetails gst_sinesrc_details = {
+ "Sine-wave src",
+ "Source/Audio",
+ "Create a sine wave of a given frequency and volume",
+ VERSION,
+ "Erik Walthinsen ",
+ "(C) 1999",
+};
+
+
+/* SineSrc signals and args */
+enum {
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum {
+ ARG_0,
+ ARG_VOLUME,
+ ARG_FORMAT,
+ ARG_SAMPLERATE,
+ ARG_FREQ,
+ ARG_TABLESIZE,
+ ARG_BUFFER_SIZE,
+};
+
+// FIXME: this is not core business...
+GST_PADTEMPLATE_FACTORY (sinesrc_src_factory,
+ "src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_CAPS_NEW (
+ "sinesrc_src",
+ "audio/raw",
+ "format", GST_PROPS_STRING ("int"),
+ "law", GST_PROPS_INT (0),
+ "endianness", GST_PROPS_INT (G_BYTE_ORDER),
+ "signed", GST_PROPS_BOOLEAN (TRUE),
+ "width", GST_PROPS_INT (16),
+ "depth", GST_PROPS_INT (16),
+ "rate", GST_PROPS_INT_RANGE (8000, 48000),
+ "channels", GST_PROPS_INT (1)
+ )
+);
+
+static void gst_sinesrc_class_init (GstSineSrcClass *klass);
+static void gst_sinesrc_init (GstSineSrc *src);
+static GstPadNegotiateReturn gst_sinesrc_negotiate (GstPad *pad, GstCaps **caps, gpointer *data);
+static void gst_sinesrc_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void gst_sinesrc_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+//static gboolean gst_sinesrc_change_state(GstElement *element,
+// GstElementState state);
+//static void gst_sinesrc_close_audio(GstSineSrc *src);
+//static gboolean gst_sinesrc_open_audio(GstSineSrc *src);
+
+static void gst_sinesrc_update_volume(GValue *value, gpointer data);
+static void gst_sinesrc_update_freq(GValue *value, gpointer data);
+static void gst_sinesrc_populate_sinetable (GstSineSrc *src);
+static inline void gst_sinesrc_update_table_inc (GstSineSrc *src);
+static inline void gst_sinesrc_update_vol_scale (GstSineSrc *src);
+static void gst_sinesrc_force_caps (GstSineSrc *src);
+
+static GstBuffer* gst_sinesrc_get (GstPad *pad);
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_sinesrc_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_sinesrc_get_type (void)
+{
+ static GType sinesrc_type = 0;
+
+ if (!sinesrc_type) {
+ static const GTypeInfo sinesrc_info = {
+ sizeof(GstSineSrcClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)gst_sinesrc_class_init,
+ NULL,
+ NULL,
+ sizeof(GstSineSrc),
+ 0,
+ (GInstanceInitFunc)gst_sinesrc_init,
+ };
+ sinesrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstSineSrc", &sinesrc_info, 0);
+ }
+ return sinesrc_type;
+}
+
+static void
+gst_sinesrc_class_init (GstSineSrcClass *klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+
+ gobject_class = (GObjectClass*)klass;
+ gstelement_class = (GstElementClass*)klass;
+
+ parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VOLUME,
+ g_param_spec_double("volume","volume","volume",
+ 0.0, 1.0, 0.0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FORMAT,
+ g_param_spec_int("format","format","format",
+ G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SAMPLERATE,
+ g_param_spec_int("samplerate","samplerate","samplerate",
+ G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TABLESIZE,
+ g_param_spec_int("tablesize","tablesize","tablesize",
+ G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FREQ,
+ g_param_spec_double("freq","freq","freq",
+ 0.0,G_MAXDOUBLE, 440.0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFFER_SIZE,
+ g_param_spec_int("buffersize","buffersize","buffersize",
+ 0, G_MAXINT, 1024, G_PARAM_READWRITE));
+
+ gobject_class->set_property = gst_sinesrc_set_property;
+ gobject_class->get_property = gst_sinesrc_get_property;
+
+// gstelement_class->change_state = gst_sinesrc_change_state;
+}
+
+static void
+gst_sinesrc_init (GstSineSrc *src)
+{
+ GstElement *element = GST_ELEMENT(src);
+ GstDParamManager *dpman;
+
+ src->srcpad = gst_pad_new_from_template (
+ GST_PADTEMPLATE_GET (sinesrc_src_factory), "src");
+ gst_element_add_pad(GST_ELEMENT(src), src->srcpad);
+ gst_pad_set_negotiate_function (src->srcpad, gst_sinesrc_negotiate);
+
+ gst_pad_set_get_function(src->srcpad, gst_sinesrc_get);
+
+ src->format = 16;
+ src->samplerate = 44100;
+
+ src->newcaps = TRUE;
+
+ src->table_pos = 0.0;
+ src->table_size = 1024;
+ src->buffer_size=1024;
+
+ src->seq = 0;
+
+ dpman = gst_dpman_new ("sinesrc_dpman", GST_ELEMENT(src));
+ gst_dpman_add_required_dparam (dpman, "volume", G_TYPE_FLOAT, gst_sinesrc_update_volume, src);
+ gst_dpman_add_required_dparam (dpman, "freq", G_TYPE_FLOAT, gst_sinesrc_update_freq, src);
+
+ gst_dpman_set_rate_change_pad(dpman, src->srcpad);
+
+ GST_ELEMENT_DPARAM_MANAGER(element) = dpman;
+
+ gst_sinesrc_update_vol_scale(src);
+
+ gst_sinesrc_populate_sinetable(src);
+ gst_sinesrc_update_table_inc(src);
+
+}
+
+static GstPadNegotiateReturn
+gst_sinesrc_negotiate (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+ GstSineSrc *src;
+
+ if (*caps) {
+ g_return_val_if_fail (pad != NULL, GST_PAD_NEGOTIATE_FAIL);
+ src = GST_SINESRC(gst_pad_get_parent (pad));
+ src->samplerate = gst_caps_get_int (*caps, "rate");
+ gst_sinesrc_update_table_inc(src);
+ return GST_PAD_NEGOTIATE_AGREE;
+ }
+
+ return GST_PAD_NEGOTIATE_FAIL;
+}
+
+static GstBuffer *
+gst_sinesrc_get(GstPad *pad)
+{
+ GstSineSrc *src;
+ GstBuffer *buf;
+ GstDParamManager *dpman;
+
+ gint16 *samples;
+ gint i=0, frame_countdown;
+
+ g_return_val_if_fail (pad != NULL, NULL);
+ src = GST_SINESRC(gst_pad_get_parent (pad));
+
+ buf = gst_buffer_new();
+ g_return_val_if_fail (buf, NULL);
+ samples = g_new(gint16, src->buffer_size);
+ GST_BUFFER_DATA(buf) = (gpointer) samples;
+ GST_BUFFER_SIZE(buf) = 2 * src->buffer_size;
+
+ dpman = GST_ELEMENT_DPARAM_MANAGER(GST_ELEMENT(src));
+ frame_countdown = GST_DPMAN_FIRST_COUNTDOWN(dpman, src->buffer_size, 0LL);
+
+ while(GST_DPMAN_COUNTDOWN(dpman, frame_countdown, i)) {
+ src->table_lookup = (gint)(src->table_pos);
+ src->table_lookup_next = src->table_lookup + 1;
+ src->table_interp = src->table_pos - src->table_lookup;
+
+ // wrap the array lookups if we're out of bounds
+ if (src->table_lookup_next >= src->table_size){
+ src->table_lookup_next -= src->table_size;
+ if (src->table_lookup >= src->table_size){
+ src->table_lookup -= src->table_size;
+ src->table_pos -= src->table_size;
+ }
+ }
+
+ src->table_pos += src->table_inc;
+
+ //no interpolation
+ //samples[i] = src->table_data[src->table_lookup]
+ // * src->vol_scale;
+
+ //linear interpolation
+ samples[i++] = ((src->table_interp
+ *(src->table_data[src->table_lookup_next]
+ -src->table_data[src->table_lookup]
+ )
+ )+src->table_data[src->table_lookup]
+ )* src->vol_scale;
+ }
+
+ if (src->newcaps) {
+ gst_sinesrc_force_caps(src);
+ }
+
+ return buf;
+}
+
+static void
+gst_sinesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GstSineSrc *src;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_SINESRC(object));
+ src = GST_SINESRC(object);
+
+ switch (prop_id) {
+ case ARG_VOLUME:
+ src->volume = (gfloat)g_value_get_double (value);
+ gst_sinesrc_update_vol_scale(src);
+ break;
+ case ARG_FORMAT:
+ src->format = g_value_get_int (value);
+ src->newcaps=TRUE;
+ break;
+ case ARG_SAMPLERATE:
+ src->samplerate = g_value_get_int (value);
+ src->newcaps=TRUE;
+ gst_sinesrc_update_table_inc(src);
+ break;
+ case ARG_FREQ: {
+ if (g_value_get_double (value) <= 0.0 || g_value_get_double (value) > src->samplerate/2)
+ break;
+ src->freq = (gfloat)g_value_get_double (value);
+ gst_sinesrc_update_table_inc(src);
+ break;
+ case ARG_TABLESIZE:
+ src->table_size = g_value_get_int (value);
+ gst_sinesrc_populate_sinetable(src);
+ gst_sinesrc_update_table_inc(src);
+ break;
+ case ARG_BUFFER_SIZE:
+ src->buffer_size = g_value_get_int (value);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void
+gst_sinesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GstSineSrc *src;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_SINESRC(object));
+ src = GST_SINESRC(object);
+
+ switch (prop_id) {
+ case ARG_VOLUME:
+ g_value_set_double (value, (gdouble)(src->volume));
+ break;
+ case ARG_FORMAT:
+ g_value_set_int (value, src->format);
+ break;
+ case ARG_SAMPLERATE:
+ g_value_set_int (value, src->samplerate);
+ break;
+ case ARG_FREQ:
+ g_value_set_double (value, (gdouble)(src->freq));
+ break;
+ case ARG_TABLESIZE:
+ g_value_set_int (value, src->table_size);
+ break;
+ case ARG_BUFFER_SIZE:
+ g_value_set_int (value, src->buffer_size);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/*
+static gboolean gst_sinesrc_change_state(GstElement *element,
+ GstElementState state) {
+ g_return_if_fail(GST_IS_SINESRC(element));
+
+ switch (state) {
+ case GST_STATE_RUNNING:
+ if (!gst_sinesrc_open_audio(GST_SINESRC(element)))
+ return FALSE;
+ break;
+ case ~GST_STATE_RUNNING:
+ gst_sinesrc_close_audio(GST_SINESRC(element));
+ break;
+ default:
+ break;
+ }
+
+ if (GST_ELEMENT_CLASS(parent_class)->change_state)
+ return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
+ return TRUE;
+}
+*/
+
+static void
+gst_sinesrc_populate_sinetable (GstSineSrc *src)
+{
+ gint i;
+ gdouble pi2scaled = M_PI * 2 / src->table_size;
+ gfloat *table = g_new(gfloat, src->table_size);
+
+ for(i=0 ; i < src->table_size ; i++){
+ table[i] = (gfloat)sin(i * pi2scaled);
+ }
+
+ g_free(src->table_data);
+ src->table_data = table;
+}
+
+static void
+gst_sinesrc_update_volume(GValue *value, gpointer data)
+{
+ GstSineSrc *src = (GstSineSrc*)data;
+ g_return_if_fail(GST_IS_SINESRC(src));
+
+ src->volume = g_value_get_float(value);
+ src->vol_scale = 32767.0 * src->volume;
+}
+
+static void
+gst_sinesrc_update_freq(GValue *value, gpointer data)
+{
+ GstSineSrc *src = (GstSineSrc*)data;
+ g_return_if_fail(GST_IS_SINESRC(src));
+
+ src->freq = g_value_get_float(value);
+ src->table_inc = src->table_size * src->freq / src->samplerate;
+}
+
+static inline void
+gst_sinesrc_update_table_inc (GstSineSrc *src)
+{
+ src->table_inc = src->table_size * src->freq / src->samplerate;
+}
+
+static inline void
+gst_sinesrc_update_vol_scale (GstSineSrc *src)
+{
+ src->vol_scale = 32767.0 * src->volume;
+}
+
+static void
+gst_sinesrc_force_caps(GstSineSrc *src) {
+ GstCaps *caps;
+
+ if (!src->newcaps)
+ return;
+
+ src->newcaps=FALSE;
+
+ caps = gst_caps_new (
+ "sinesrc_src_caps",
+ "audio/raw",
+ gst_props_new (
+ "format", GST_PROPS_STRING ("int"),
+ "law", GST_PROPS_INT (0),
+ "endianness", GST_PROPS_INT (G_BYTE_ORDER),
+ "signed", GST_PROPS_BOOLEAN (TRUE),
+ "width", GST_PROPS_INT (16),
+ "depth", GST_PROPS_INT (16),
+ "rate", GST_PROPS_INT (src->samplerate),
+ "channels", GST_PROPS_INT (1),
+ NULL
+ )
+ );
+
+ gst_pad_set_caps (src->srcpad, caps);
+}
+
+gboolean
+gst_sinesrc_factory_init (GstElementFactory *factory)
+{
+ gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sinesrc_src_factory));
+
+ return TRUE;
+}
diff --git a/gst/elements/gstsinesrc.h b/gst/elements/gstsinesrc.h
new file mode 100644
index 0000000000..58e03fd72b
--- /dev/null
+++ b/gst/elements/gstsinesrc.h
@@ -0,0 +1,96 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstsinesrc.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_SINESRC_H__
+#define __GST_SINESRC_H__
+
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+GstElementDetails gst_sinesrc_details;
+
+
+#define GST_TYPE_SINESRC \
+ (gst_sinesrc_get_type())
+#define GST_SINESRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SINESRC,GstSineSrc))
+#define GST_SINESRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SINESRC,GstSineSrcClass))
+#define GST_IS_SINESRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SINESRC))
+#define GST_IS_SINESRC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SINESRC))
+
+typedef struct _GstSineSrc GstSineSrc;
+typedef struct _GstSineSrcClass GstSineSrcClass;
+
+struct _GstSineSrc {
+ GstElement element;
+
+ /* pads */
+ GstPad *srcpad;
+
+ /* parameters */
+ gfloat volume;
+ gfloat freq;
+ gfloat vol_scale;
+
+ /* lookup table data */
+ gfloat *table_data;
+ gdouble table_pos;
+ gdouble table_inc;
+ gint table_size;
+ gdouble table_interp;
+ gint table_lookup;
+ gint table_lookup_next;
+
+ /* audio parameters */
+ gint format;
+ gint samplerate;
+
+ gint buffer_size;
+ gulong seq;
+
+ gboolean newcaps;
+
+};
+
+struct _GstSineSrcClass {
+ GstElementClass parent_class;
+};
+
+GType gst_sinesrc_get_type(void);
+gboolean gst_sinesrc_factory_init (GstElementFactory *factory);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_SINESRC_H__ */
diff --git a/gst/elements/gsttee.c b/gst/elements/gsttee.c
index 729b95ec03..d7e0544bb0 100644
--- a/gst/elements/gsttee.c
+++ b/gst/elements/gsttee.c
@@ -56,7 +56,7 @@ GST_PADTEMPLATE_FACTORY (tee_src_factory,
static void gst_tee_class_init (GstTeeClass *klass);
static void gst_tee_init (GstTee *tee);
-static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp);
+static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp, const gchar *unused);
static void gst_tee_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
@@ -127,7 +127,7 @@ gst_tee_init (GstTee *tee)
}
static GstPad*
-gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ)
+gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
{
gchar *name;
GstPad *srcpad;
diff --git a/gst/gobject2gtk.c b/gst/gobject2gtk.c
index c53aa366ad..72165d39c8 100644
--- a/gst/gobject2gtk.c
+++ b/gst/gobject2gtk.c
@@ -6,6 +6,24 @@
#include "gobject2gtk.h"
+// list functions not in glib 1.2
+GList *
+g_list_delete_link (GList *list, GList *llink)
+{
+ GList *temp = g_list_remove_link(list, llink);
+ g_list_free(llink);
+ return temp;
+}
+
+GSList *
+g_slist_delete_link (GSList *list, GSList *llink)
+{
+ GSList *temp = g_slist_remove_link(list, llink);
+ g_slist_free(llink);
+ return temp;
+}
+
+
// GObject dummy implementation
static void
@@ -324,4 +342,3 @@ gint* g_signal_list_ids (GType type, guint *n_ids)
return class->signals;
}
-
diff --git a/gst/gobject2gtk.h b/gst/gobject2gtk.h
index 309fe97b0a..6201c12a78 100644
--- a/gst/gobject2gtk.h
+++ b/gst/gobject2gtk.h
@@ -14,6 +14,12 @@
#define G_PI_4 0.78539816339744830962E0
#define G_SQRT2 1.4142135623730950488E0
+// lists functions not in glib 1.2
+GList *g_list_delete_link (GList *list, GList *llink);
+GSList *g_slist_delete_link (GSList *list, GSList *llink);
+
+
+// GObject
typedef struct _GObject GObject;
typedef struct _GObjectClass GObjectClass;
@@ -53,35 +59,35 @@ typedef struct _GObjectClass GObjectClass;
#define G_TYPE_PARAM GTK_TYPE_PARAM
// marshallers
-#define g_cclosure_marshal_VOID__VOID gtk_marshal_NONE__NONE
-#define g_cclosure_marshal_VOID__BOOLEAN gtk_marshal_NONE__BOOL
-#define g_cclosure_marshal_VOID__CHAR gtk_marshal_NONE__CHAR
-#define g_cclosure_marshal_VOID__UCHAR gtk_marshal_NONE__UCHAR
-#define g_cclosure_marshal_VOID__INT gtk_marshal_NONE__INT
-#define g_cclosure_marshal_VOID__UINT gtk_marshal_NONE__UINT
-#define g_cclosure_marshal_VOID__LONG gtk_marshal_NONE__LONG
-#define g_cclosure_marshal_VOID__ULONG gtk_marshal_NONE__ULONG
-#define g_cclosure_marshal_VOID__ENUM gtk_marshal_NONE__ENUM
-#define g_cclosure_marshal_VOID__FLAGS gtk_marshal_NONE__FLAGS
-#define g_cclosure_marshal_VOID__FLOAT gtk_marshal_NONE__FLOAT
-#define g_cclosure_marshal_VOID__DOUBLE gtk_marshal_NONE__DOUBLE
-#define g_cclosure_marshal_VOID__STRING gtk_marshal_NONE__STRING
-#define g_cclosure_marshal_VOID__PARAM gtk_marshal_NONE__PARAM
-#define g_cclosure_marshal_VOID__BOXED gtk_marshal_NONE__BOXED
-#define g_cclosure_marshal_VOID__POINTER gtk_marshal_NONE__POINTER
-#define g_cclosure_marshal_VOID__OBJECT gtk_marshal_NONE__OBJECT
-#define g_cclosure_marshal_STRING__OBJECT_POINTER gtk_marshal_STRING__OBJECT_POINTER
-#define g_cclosure_marshal_VOID__UINT_POINTER gtk_marshal_NONE__UINT_POINTER
+#define g_cclosure_marshal_VOID__VOID gtk_marshal_NONE__NONE
+#define g_cclosure_marshal_VOID__BOOLEAN gtk_marshal_NONE__BOOL
+#define g_cclosure_marshal_VOID__CHAR gtk_marshal_NONE__CHAR
+#define g_cclosure_marshal_VOID__UCHAR gtk_marshal_NONE__UCHAR
+#define g_cclosure_marshal_VOID__INT gtk_marshal_NONE__INT
+#define g_cclosure_marshal_VOID__UINT gtk_marshal_NONE__UINT
+#define g_cclosure_marshal_VOID__LONG gtk_marshal_NONE__LONG
+#define g_cclosure_marshal_VOID__ULONG gtk_marshal_NONE__ULONG
+#define g_cclosure_marshal_VOID__ENUM gtk_marshal_NONE__ENUM
+#define g_cclosure_marshal_VOID__FLAGS gtk_marshal_NONE__FLAGS
+#define g_cclosure_marshal_VOID__FLOAT gtk_marshal_NONE__FLOAT
+#define g_cclosure_marshal_VOID__DOUBLE gtk_marshal_NONE__DOUBLE
+#define g_cclosure_marshal_VOID__STRING gtk_marshal_NONE__STRING
+#define g_cclosure_marshal_VOID__PARAM gtk_marshal_NONE__PARAM
+#define g_cclosure_marshal_VOID__BOXED gtk_marshal_NONE__BOXED
+#define g_cclosure_marshal_VOID__POINTER gtk_marshal_NONE__POINTER
+#define g_cclosure_marshal_VOID__OBJECT gtk_marshal_NONE__OBJECT
+#define g_cclosure_marshal_STRING__OBJECT_POINTER gtk_marshal_STRING__POINTER_POINTER
+#define g_cclosure_marshal_VOID__UINT_POINTER gtk_marshal_NONE__UINT_POINTER
-#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT
-#define gst_marshal_VOID__INT gtk_marshal_NONE__INT
-#define gst_marshal_VOID__STRING gtk_marshal_NONE__STRING
#define gst_marshal_VOID__VOID gtk_marshal_NONE__NONE
#define gst_marshal_VOID__BOOLEAN gtk_marshal_NONE__BOOL
+#define gst_marshal_VOID__INT gtk_marshal_NONE__INT
+#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT
+#define gst_marshal_VOID__STRING gtk_marshal_NONE__STRING
#define gst_marshal_VOID__POINTER gtk_marshal_NONE__POINTER
-#define gst_marshal_VOID__OBJECT gtk_marshal_NONE__POINTER
-#define gst_marshal_VOID__OBJECT_POINTER gtk_marshal_NONE__POINTER_POINTER
-#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT
+#define gst_marshal_VOID__OBJECT gtk_marshal_NONE__POINTER
+#define gst_marshal_VOID__OBJECT_POINTER gtk_marshal_NONE__POINTER_POINTER
+#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT
/* General macros */
#ifdef __cplusplus
@@ -217,6 +223,10 @@ gtk_signal_handler_pending ((GtkObject *)object,name,may_block)
gint* g_signal_list_ids (GType type, guint *n_ids);
+// lists
+GSList* g_slist_delete_link (GSList *list, GSList *link) __attribute__ ((no_instrument_function));
+
+
// arguments/parameters
// first define GValue and GParamSpec
diff --git a/gst/gst.c b/gst/gst.c
index d3a9f63f5a..8ecacbacfc 100644
--- a/gst/gst.c
+++ b/gst/gst.c
@@ -24,6 +24,7 @@
#include "gst_private.h"
+#include "gstversion.h"
#include "gstcpu.h"
#include "gsttype.h"
#include "gstplugin.h"
@@ -38,6 +39,7 @@
#endif
#define MAX_PATH_SPLIT 16
+#define GST_PLUGIN_SEPARATOR ","
gchar *_gst_progname;
@@ -47,6 +49,9 @@ extern gboolean _gst_plugin_spew;
static gboolean gst_init_check (int *argc, gchar ***argv);
+static void load_plugin_func (gpointer data, gpointer user_data);
+
+static GSList *preload_plugins = NULL;
const gchar *g_log_domain_gstreamer = "GStreamer";
@@ -105,7 +110,12 @@ gst_init (int *argc, char **argv[])
GST_INFO (GST_CAT_GST_INIT, "Initializing GStreamer Core Library");
+ gst_object_get_type ();
+ gst_pad_get_type ();
+ gst_real_pad_get_type ();
+ gst_ghost_pad_get_type ();
gst_elementfactory_get_type ();
+ gst_element_get_type ();
gst_typefactory_get_type ();
#ifndef GST_DISABLE_AUTOPLUG
gst_autoplugfactory_get_type ();
@@ -115,9 +125,17 @@ gst_init (int *argc, char **argv[])
_gst_props_initialize ();
_gst_caps_initialize ();
_gst_plugin_initialize ();
+ _gst_event_initialize ();
_gst_buffer_initialize ();
_gst_buffer_pool_initialize ();
+ /* if we need to preload plugins */
+ if (preload_plugins) {
+ g_slist_foreach (preload_plugins, load_plugin_func, NULL);
+ g_slist_free (preload_plugins);
+ preload_plugins = NULL;
+ }
+
/* register some standard builtin types */
gst_elementfactory_new ("bin", gst_bin_get_type (), &gst_bin_details);
gst_elementfactory_new ("pipeline", gst_pipeline_get_type (), &gst_pipeline_details);
@@ -137,23 +155,23 @@ gst_init (int *argc, char **argv[])
}
static void
-gst_add_paths_func (const gchar *pathlist)
+split_and_iterate (const gchar *stringlist, gchar *separator, GFunc iterator)
{
- gchar **paths;
+ gchar **strings;
gint j = 0;
- gchar *lastpath = g_strdup (pathlist);
+ gchar *lastlist = g_strdup (stringlist);
- while (lastpath) {
- paths = g_strsplit (lastpath, G_SEARCHPATH_SEPARATOR_S, MAX_PATH_SPLIT);
- g_free (lastpath);
- lastpath = NULL;
+ while (lastlist) {
+ strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
+ //strings = g_strsplit (lastlist, G_SEARCHPATH_SEPARATOR_S, MAX_PATH_SPLIT);
+ g_free (lastlist);
+ lastlist = NULL;
- while (paths[j]) {
- GST_INFO (GST_CAT_GST_INIT, "Adding plugin path: \"%s\"", paths[j]);
- gst_plugin_add_path (paths[j]);
+ while (strings[j]) {
+ iterator (strings[j], NULL);
if (++j == MAX_PATH_SPLIT) {
- lastpath = g_strdup (paths[j]);
- g_strfreev (paths);
+ lastlist = g_strdup (strings[j]);
+ g_strfreev (strings);
j=0;
break;
}
@@ -161,6 +179,33 @@ gst_add_paths_func (const gchar *pathlist)
}
}
+static void
+add_path_func (gpointer data, gpointer user_data)
+{
+ GST_INFO (GST_CAT_GST_INIT, "Adding plugin path: \"%s\"", (gchar *)data);
+ gst_plugin_add_path ((gchar *)data);
+}
+
+static void
+prepare_for_load_plugin_func (gpointer data, gpointer user_data)
+{
+ preload_plugins = g_slist_prepend (preload_plugins, data);
+}
+
+static void
+load_plugin_func (gpointer data, gpointer user_data)
+{
+ gboolean ret;
+ ret = gst_plugin_load ((gchar *)data);
+ if (ret)
+ GST_INFO (GST_CAT_GST_INIT, "Loaded plugin: \"%s\"", (gchar *)data);
+ else
+ GST_INFO (GST_CAT_GST_INIT, "Failed to load plugin: \"%s\"", (gchar *)data);
+
+ g_free (data);
+}
+
+
/* returns FALSE if the program can be aborted */
static gboolean
gst_init_check (int *argc,
@@ -226,7 +271,12 @@ gst_init_check (int *argc,
(*argv)[i] = NULL;
}
else if (!strncmp ("--gst-plugin-path=", (*argv)[i], 17)) {
- gst_add_paths_func ((*argv)[i]+18);
+ split_and_iterate ((*argv)[i]+18, G_SEARCHPATH_SEPARATOR_S, add_path_func);
+
+ (*argv)[i] = NULL;
+ }
+ else if (!strncmp ("--gst-plugin-load=", (*argv)[i], 17)) {
+ split_and_iterate ((*argv)[i]+18, ",", prepare_for_load_plugin_func);
(*argv)[i] = NULL;
}
@@ -257,7 +307,7 @@ gst_init_check (int *argc,
/* check for ENV variables */
{
const gchar *plugin_path = g_getenv("GST_PLUGIN_PATH");
- gst_add_paths_func (plugin_path);
+ split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func);
}
if (showhelp) {
@@ -272,6 +322,8 @@ gst_init_check (int *argc,
g_print (" --gst-plugin-spew Enable printout of errors while loading GST plugins\n");
g_print (" --gst-plugin-path=PATH Add directories separated with '%s' to the plugin search path\n",
G_SEARCHPATH_SEPARATOR_S);
+ g_print (" --gst-plugin-load=PLUGINS Load plugins separated with '%s'\n",
+ GST_PLUGIN_SEPARATOR);
g_print ("\n Mask (to be OR'ed) info/debug FLAGS \n");
g_print ("--------------------------------------------------------\n");
@@ -323,3 +375,24 @@ gst_main_quit (void)
gtk_main_quit ();
#endif
}
+
+/**
+ * gst_version:
+ * @major: pointer to a guint to store the major version number
+ * @minor: pointer to a guint to store the minor version number
+ * @micro: pointer to a guint to store the micro version number
+ *
+ * Gets the version number of the GStreamer library
+ */
+void
+gst_version (guint *major, guint *minor, guint *micro)
+{
+ g_return_if_fail (major);
+ g_return_if_fail (minor);
+ g_return_if_fail (micro);
+
+ *major = GST_VERSION_MAJOR;
+ *minor = GST_VERSION_MINOR;
+ *micro = GST_VERSION_MICRO;
+}
+
diff --git a/gst/gst.h b/gst/gst.h
index 2addc92658..032d5d2c57 100644
--- a/gst/gst.h
+++ b/gst/gst.h
@@ -50,6 +50,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/gst/gstautoplug.c b/gst/gstautoplug.c
index af6a29f94e..612cd4b9ce 100644
--- a/gst/gstautoplug.c
+++ b/gst/gstautoplug.c
@@ -21,6 +21,9 @@
*/
//#define GST_DEBUG_ENABLED
+
+#include
+
#include "gst_private.h"
#include "gstautoplug.h"
@@ -168,8 +171,10 @@ gst_autoplug_to_renderers (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *
static void gst_autoplugfactory_class_init (GstAutoplugFactoryClass *klass);
static void gst_autoplugfactory_init (GstAutoplugFactory *factory);
+#ifndef GST_DISABLE_REGISTRY
static xmlNodePtr gst_autoplugfactory_save_thyself (GstObject *object, xmlNodePtr parent);
static void gst_autoplugfactory_restore_thyself (GstObject *object, xmlNodePtr parent);
+#endif
static GstPluginFeatureClass *factory_parent_class = NULL;
//static guint gst_autoplugfactory_signals[LAST_SIGNAL] = { 0 };
@@ -211,8 +216,10 @@ gst_autoplugfactory_class_init (GstAutoplugFactoryClass *klass)
factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
+#ifndef GST_DISABLE_REGISTRY
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_autoplugfactory_save_thyself);
gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_autoplugfactory_restore_thyself);
+#endif
_gst_autoplugfactories = NULL;
}
@@ -361,6 +368,7 @@ gst_autoplugfactory_make (const gchar *name)
return gst_autoplugfactory_create (factory);;
}
+#ifndef GST_DISABLE_REGISTRY
static xmlNodePtr
gst_autoplugfactory_save_thyself (GstObject *object, xmlNodePtr parent)
{
@@ -407,3 +415,4 @@ gst_autoplugfactory_restore_thyself (GstObject *object, xmlNodePtr parent)
children = children->next;
}
}
+#endif /* GST_DISABLE_REGISTRY */
diff --git a/gst/gstbin.c b/gst/gstbin.c
index 1b97b98a5b..4396fe3da4 100644
--- a/gst/gstbin.c
+++ b/gst/gstbin.c
@@ -113,16 +113,17 @@ gst_bin_class_init (GstBinClass *klass)
gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
GST_TYPE_ELEMENT);
- klass->change_state_type = gst_bin_change_state_type;
- klass->iterate = gst_bin_iterate_func;
+ klass->change_state_type = GST_DEBUG_FUNCPTR (gst_bin_change_state_type);
+ klass->iterate = GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
#ifndef GST_DISABLE_LOADSAVE
- gstobject_class->save_thyself = gst_bin_save_thyself;
- gstobject_class->restore_thyself = gst_bin_restore_thyself;
+ gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
+ gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
#endif
- gstelement_class->change_state = gst_bin_change_state;
- gobject_class->dispose = gst_bin_dispose;
+ gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
+
+ gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
}
static void
@@ -644,7 +645,7 @@ gst_bin_restore_thyself (GstObject *object,
field = field->next;
}
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE */
/**
diff --git a/gst/gstbuffer.c b/gst/gstbuffer.c
index fc61d55907..c330b2e1ce 100644
--- a/gst/gstbuffer.c
+++ b/gst/gstbuffer.c
@@ -27,6 +27,8 @@
#include "gstbuffer.h"
+GType _gst_buffer_type;
+
static GMemChunk *_gst_buffer_chunk;
static GMutex *_gst_buffer_chunk_lock;
@@ -34,6 +36,17 @@ void
_gst_buffer_initialize (void)
{
int buffersize = sizeof(GstBuffer);
+ static const GTypeInfo buffer_info = {
+ 0, // sizeof(class),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0, // sizeof(object),
+ 0,
+ NULL,
+ };
// round up to the nearest 32 bytes for cache-line and other efficiencies
buffersize = (((buffersize-1) / 32) + 1) * 32;
@@ -42,6 +55,8 @@ _gst_buffer_initialize (void)
buffersize * 32, G_ALLOC_AND_FREE);
_gst_buffer_chunk_lock = g_mutex_new ();
+
+ _gst_buffer_type = g_type_register_static (G_TYPE_INT, "GstBuffer", &buffer_info, 0);
}
/**
@@ -52,7 +67,7 @@ _gst_buffer_initialize (void)
* Returns: new buffer
*/
GstBuffer*
-gst_buffer_new(void)
+gst_buffer_new (void)
{
GstBuffer *buffer;
@@ -61,6 +76,8 @@ gst_buffer_new(void)
g_mutex_unlock (_gst_buffer_chunk_lock);
GST_INFO (GST_CAT_BUFFER,"creating new buffer %p",buffer);
+ GST_DATA_TYPE(buffer) = _gst_buffer_type;
+
buffer->lock = g_mutex_new ();
#ifdef HAVE_ATOMIC_H
atomic_set (&buffer->refcount, 1);
@@ -78,7 +95,7 @@ gst_buffer_new(void)
buffer->pool_private = NULL;
buffer->free = NULL;
buffer->copy = NULL;
-
+
return buffer;
}
@@ -91,18 +108,21 @@ gst_buffer_new(void)
* Returns: new buffer
*/
GstBuffer*
-gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size)
+gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size)
{
GstBuffer *buffer;
g_return_val_if_fail (pool != NULL, NULL);
g_return_val_if_fail (pool->buffer_new != NULL, NULL);
- buffer = pool->buffer_new (pool, location, size, pool->user_data);
+ buffer = pool->buffer_new (pool, offset, size, pool->user_data);
buffer->pool = pool;
buffer->free = pool->buffer_free;
buffer->copy = pool->buffer_copy;
+ GST_INFO (GST_CAT_BUFFER,"creating new buffer %p from pool %p (size %x, offset %x)",
+ buffer, pool, size, offset);
+
return buffer;
}
@@ -124,13 +144,16 @@ gst_buffer_create_sub (GstBuffer *parent,
GstBuffer *buffer;
g_return_val_if_fail (parent != NULL, NULL);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(parent) > 0, NULL);
g_return_val_if_fail (size > 0, NULL);
g_return_val_if_fail ((offset+size) <= parent->size, NULL);
g_mutex_lock (_gst_buffer_chunk_lock);
buffer = g_mem_chunk_alloc (_gst_buffer_chunk);
+ GST_DATA_TYPE(buffer) = _gst_buffer_type;
g_mutex_unlock (_gst_buffer_chunk_lock);
- GST_INFO (GST_CAT_BUFFER,"creating new subbuffer %p from parent %p", buffer, parent);
+ GST_INFO (GST_CAT_BUFFER,"creating new subbuffer %p from parent %p (size %u, offset %u)",
+ buffer, parent, size, offset);
buffer->lock = g_mutex_new ();
#ifdef HAVE_ATOMIC_H
@@ -166,7 +189,7 @@ gst_buffer_create_sub (GstBuffer *parent,
gst_buffer_ref (parent);
buffer->pool = NULL;
- // return the new subbuffer
+
return buffer;
}
@@ -192,6 +215,8 @@ gst_buffer_append (GstBuffer *buffer,
g_return_val_if_fail (buffer != NULL, NULL);
g_return_val_if_fail (append != NULL, NULL);
g_return_val_if_fail (buffer->pool == NULL, NULL);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0, NULL);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(append) > 0, NULL);
GST_INFO (GST_CAT_BUFFER,"appending buffers %p and %p",buffer,append);
@@ -226,12 +251,15 @@ gst_buffer_append (GstBuffer *buffer,
*
* destroy the buffer
*/
-void gst_buffer_destroy (GstBuffer *buffer)
+void
+gst_buffer_destroy (GstBuffer *buffer)
{
g_return_if_fail (buffer != NULL);
- GST_INFO (GST_CAT_BUFFER,"freeing %sbuffer %p", (buffer->parent?"sub":""),buffer);
+ GST_INFO (GST_CAT_BUFFER, "freeing %sbuffer %p",
+ (buffer->parent?"sub":""),
+ buffer);
// free the data only if there is some, DONTFREE isn't set, and not sub
if (GST_BUFFER_DATA (buffer) &&
@@ -252,6 +280,11 @@ void gst_buffer_destroy (GstBuffer *buffer)
g_mutex_free (buffer->lock);
//g_print("freed mutex\n");
+#ifdef GST_DEBUG_ENABLED
+ // make it hard to reuse by mistake
+ memset (buffer, 0, sizeof (GstBuffer));
+#endif
+
// remove it entirely from memory
g_mutex_lock (_gst_buffer_chunk_lock);
g_mem_chunk_free (_gst_buffer_chunk,buffer);
@@ -268,44 +301,19 @@ void
gst_buffer_ref (GstBuffer *buffer)
{
g_return_if_fail (buffer != NULL);
+ g_return_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0);
- GST_DEBUG (0,"referencing buffer %p\n", buffer);
+ GST_INFO (GST_CAT_BUFFER, "ref buffer %p\n", buffer);
#ifdef HAVE_ATOMIC_H
- //g_return_if_fail(atomic_read(&(buffer->refcount)) > 0);
atomic_inc (&(buffer->refcount));
#else
- g_return_if_fail (buffer->refcount > 0);
GST_BUFFER_LOCK (buffer);
buffer->refcount++;
GST_BUFFER_UNLOCK (buffer);
#endif
}
-/**
- * gst_buffer_ref_by_count:
- * @buffer: the GstBuffer to reference
- * @count: a number
- *
- * Increment the refcount of this buffer by the given number.
- */
-void
-gst_buffer_ref_by_count (GstBuffer *buffer, int count)
-{
- g_return_if_fail (buffer != NULL);
- g_return_if_fail (count > 0);
-
-#ifdef HAVE_ATOMIC_H
- g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
- atomic_add (count, &(buffer->refcount));
-#else
- g_return_if_fail (buffer->refcount > 0);
- GST_BUFFER_LOCK (buffer);
- buffer->refcount += count;
- GST_BUFFER_UNLOCK (buffer);
-#endif
-}
-
/**
* gst_buffer_unref:
* @buffer: the GstBuffer to unref
@@ -319,14 +327,13 @@ gst_buffer_unref (GstBuffer *buffer)
gint zero;
g_return_if_fail (buffer != NULL);
+ g_return_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0);
- GST_DEBUG (0,"unreferencing buffer %p\n", buffer);
+ GST_INFO (GST_CAT_BUFFER, "unref buffer %p\n", buffer);
#ifdef HAVE_ATOMIC_H
- g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
zero = atomic_dec_and_test (&(buffer->refcount));
#else
- g_return_if_fail (buffer->refcount > 0);
GST_BUFFER_LOCK (buffer);
buffer->refcount--;
zero = (buffer->refcount == 0);
@@ -352,6 +359,8 @@ gst_buffer_copy (GstBuffer *buffer)
{
GstBuffer *newbuf;
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0, NULL);
+
// if a copy function exists, use it, else copy the bytes
if (buffer->copy != NULL) {
newbuf = (buffer->copy)(buffer);
@@ -391,7 +400,11 @@ gst_buffer_copy (GstBuffer *buffer)
gboolean
gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
{
- return ((buf1->parent == buf2->parent) &&
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf1) > 0, FALSE);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf2) > 0, FALSE);
+
+ return (buf1->parent && buf2->parent &&
+ (buf1->parent == buf2->parent) &&
((buf1->data + buf1->size) == buf2->data));
}
@@ -420,38 +433,43 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
{
GstBuffer *newbuf;
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf1) > 0, NULL);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf2) > 0, NULL);
+
// make sure buf1 has a lower address than buf2
if (buf1->data > buf2->data) {
GstBuffer *tmp = buf1;
+ g_print ("swapping buffers\n");
buf1 = buf2;
buf2 = tmp;
}
// if the two buffers have the same parent and are adjacent
-// if ((buf1->parent == buf2->parent) &&
-// ((buf1->data + buf1->size) == buf2->data)) {
if (gst_buffer_is_span_fast(buf1,buf2)) {
// we simply create a subbuffer of the common parent
- return gst_buffer_create_sub(buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
+ newbuf = gst_buffer_create_sub (buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
}
+ else {
+ g_print ("slow path taken in buffer_span\n");
+ // otherwise we simply have to brute-force copy the buffers
+ newbuf = gst_buffer_new ();
- // otherwise we simply have to brute-force copy the buffers
- newbuf = gst_buffer_new();
+ // put in new size
+ newbuf->size = len;
+ // allocate space for the copy
+ newbuf->data = (guchar *)g_malloc(len);
+ // copy the first buffer's data across
+ memcpy(newbuf->data, buf1->data + offset, buf1->size - offset);
+ // copy the second buffer's data across
+ memcpy(newbuf->data + (buf1->size - offset), buf2->data, len - (buf1->size - offset));
- // put in new size
- newbuf->size = len;
- // allocate space for the copy
- newbuf->data = (guchar *)g_malloc(len);
- // copy the first buffer's data across
- memcpy(newbuf->data, buf1->data + offset, buf1->size - offset);
- // copy the second buffer's data across
- memcpy(newbuf->data + offset, buf2->data, len - (buf1->size - offset));
+ if (newbuf->offset != -1)
+ newbuf->offset = buf1->offset + offset;
+ newbuf->timestamp = buf1->timestamp;
+ if (buf2->maxage > buf1->maxage) newbuf->maxage = buf2->maxage;
+ else newbuf->maxage = buf1->maxage;
- if (newbuf->offset != -1)
- newbuf->offset = buf1->offset + offset;
- newbuf->timestamp = buf1->timestamp;
- if (buf2->maxage > buf1->maxage) newbuf->maxage = buf2->maxage;
- else newbuf->maxage = buf1->maxage;
+ }
return newbuf;
}
@@ -475,5 +493,5 @@ GstBuffer *
gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2)
{
// we're just a specific case of the more general gst_buffer_span()
- return gst_buffer_span(buf1, 0, buf2, buf1->size + buf2->size);
+ return gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
}
diff --git a/gst/gstbuffer.h b/gst/gstbuffer.h
index 269bf3ee0e..9eef49c8d0 100644
--- a/gst/gstbuffer.h
+++ b/gst/gstbuffer.h
@@ -24,6 +24,18 @@
#ifndef __GST_BUFFER_H__
#define __GST_BUFFER_H__
+//
+// Define this to add file:line info to each GstBuffer showing
+// the location in the source code where the buffer was created.
+//
+// #define GST_BUFFER_WHERE
+//
+// Then in gdb, you can `call gst_buffer_print_live()' to get a list
+// of allocated GstBuffers and also the file:line where they were
+// allocated.
+//
+
+#include
#include
#ifdef HAVE_CONFIG_H
@@ -39,18 +51,16 @@
extern "C" {
#endif /* __cplusplus */
+extern GType _gst_buffer_type;
-#define GST_BUFFER(buf) \
- ((GstBuffer *)(buf))
+#define GST_TYPE_BUFFER (_gst_buffer_type)
+#define GST_BUFFER(buf) ((GstBuffer *)(buf))
+#define GST_IS_BUFFER(buf) (GST_DATA_TYPE(buf) == GST_TYPE_BUFFER)
-#define GST_BUFFER_FLAGS(buf) \
- (GST_BUFFER(buf)->flags)
-#define GST_BUFFER_FLAG_IS_SET(buf,flag) \
- (GST_BUFFER_FLAGS(buf) & (1<<(flag)))
-#define GST_BUFFER_FLAG_SET(buf,flag) \
- G_STMT_START{ (GST_BUFFER_FLAGS(buf) |= (1<<(flag))); }G_STMT_END
-#define GST_BUFFER_FLAG_UNSET(buf,flag) \
- G_STMT_START{ (GST_BUFFER_FLAGS(buf) &= ~(1<<(flag))); }G_STMT_END
+#define GST_BUFFER_FLAGS(buf) (GST_BUFFER(buf)->flags)
+#define GST_BUFFER_FLAG_IS_SET(buf,flag) (GST_BUFFER_FLAGS(buf) & (1<<(flag)))
+#define GST_BUFFER_FLAG_SET(buf,flag) G_STMT_START{ (GST_BUFFER_FLAGS(buf) |= (1<<(flag))); }G_STMT_END
+#define GST_BUFFER_FLAG_UNSET(buf,flag) G_STMT_START{ (GST_BUFFER_FLAGS(buf) &= ~(1<<(flag))); }G_STMT_END
#define GST_BUFFER_DATA(buf) (GST_BUFFER(buf)->data)
@@ -82,7 +92,6 @@ typedef enum {
} GstBufferFlags;
-
typedef struct _GstBuffer GstBuffer;
@@ -93,56 +102,56 @@ typedef GstBuffer *(*GstBufferCopyFunc) (GstBuffer *srcbuf);
#include
struct _GstBuffer {
+ GstData data_type;
+
/* locking */
- GMutex *lock;
+ GMutex *lock;
/* refcounting */
#ifdef HAVE_ATOMIC_H
- atomic_t refcount;
+ atomic_t refcount;
#define GST_BUFFER_REFCOUNT(buf) (atomic_read(&(GST_BUFFER((buf))->refcount)))
#else
- int refcount;
+ int refcount;
#define GST_BUFFER_REFCOUNT(buf) (GST_BUFFER(buf)->refcount)
#endif
/* flags */
- guint16 flags;
+ guint16 flags;
/* pointer to data, its size, and offset in original source if known */
- guchar *data;
- guint32 size;
- guint32 maxsize;
- guint32 offset;
+ guchar *data;
+ guint32 size;
+ guint32 maxsize;
+ guint32 offset;
/* timestamp */
- gint64 timestamp;
- /* max age */
- gint64 maxage;
+ gint64 timestamp;
+ gint64 maxage;
/* subbuffer support, who's my parent? */
- GstBuffer *parent;
+ GstBuffer *parent;
/* this is a pointer to the buffer pool (if any) */
- GstBufferPool *pool;
- gpointer pool_private;
+ GstBufferPool *pool;
+ gpointer pool_private;
/* utility function pointers */
- GstBufferFreeFunc free; // free the data associated with the buffer
- GstBufferCopyFunc copy; // copy the data from one buffer to another
+ GstBufferFreeFunc free; // free the data associated with the buffer
+ GstBufferCopyFunc copy; // copy the data from one buffer to another
};
/* initialisation */
void _gst_buffer_initialize (void);
/* creating a new buffer from scratch */
GstBuffer* gst_buffer_new (void);
-GstBuffer* gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size);
+GstBuffer* gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size);
/* creating a subbuffer */
GstBuffer* gst_buffer_create_sub (GstBuffer *parent, guint32 offset, guint32 size);
/* refcounting */
void gst_buffer_ref (GstBuffer *buffer);
-void gst_buffer_ref_by_count (GstBuffer *buffer, int count);
void gst_buffer_unref (GstBuffer *buffer);
/* destroying the buffer */
diff --git a/gst/gstbufferpool.c b/gst/gstbufferpool.c
index c742be0335..d04c8a22e3 100644
--- a/gst/gstbufferpool.c
+++ b/gst/gstbufferpool.c
@@ -274,6 +274,13 @@ gst_buffer_pool_destroy (GstBufferPool *pool)
g_free(pool);
}
+//
+// This is so we don't get messed up by GST_BUFFER_WHERE.
+//
+static GstBuffer *
+_pool_gst_buffer_copy (GstBuffer *buffer)
+{ return gst_buffer_copy (buffer); }
+
/**
* gst_buffer_pool_get_default:
* @buffer_size: the number of bytes this buffer will store
@@ -314,7 +321,7 @@ gst_buffer_pool_get_default (guint buffer_size, guint pool_size)
pool = gst_buffer_pool_new();
gst_buffer_pool_set_buffer_new_function (pool, gst_buffer_pool_default_buffer_new);
gst_buffer_pool_set_buffer_free_function (pool, gst_buffer_pool_default_buffer_free);
- gst_buffer_pool_set_buffer_copy_function (pool, gst_buffer_copy);
+ gst_buffer_pool_set_buffer_copy_function (pool, _pool_gst_buffer_copy);
gst_buffer_pool_set_destroy_hook (pool, gst_buffer_pool_default_destroy_hook);
def = g_new0 (GstBufferPoolDefault, 1);
diff --git a/gst/gstcaps.c b/gst/gstcaps.c
index ddb75ad500..19f68c53b1 100644
--- a/gst/gstcaps.c
+++ b/gst/gstcaps.c
@@ -545,7 +545,7 @@ gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
return FALSE;
}
-#if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) )
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
/**
* gst_caps_save_thyself:
* @caps: a capabilty to save
@@ -629,4 +629,4 @@ gst_caps_load_thyself (xmlNodePtr parent)
return result;
}
-#endif /* (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) ) */
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
diff --git a/gst/gstcaps.h b/gst/gstcaps.h
index 87482751be..77a8767d98 100644
--- a/gst/gstcaps.h
+++ b/gst/gstcaps.h
@@ -24,14 +24,7 @@
#ifndef __GST_CAPS_H__
#define __GST_CAPS_H__
-#include // NOTE: this is xml-config's fault
-
-// Include compatability defines: if libxml hasn't already defined these,
-// we have an old version 1.x
-#ifndef xmlChildrenNode
-#define xmlChildrenNode childs
-#define xmlRootNode root
-#endif
+#include
#include
@@ -118,7 +111,9 @@ GstCaps* gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd);
gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps);
+#ifndef GST_DISABLE_LOADSAVE
xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent);
GstCaps* gst_caps_load_thyself (xmlNodePtr parent);
+#endif
#endif /* __GST_CAPS_H__ */
diff --git a/gst/gstconfig.h b/gst/gstconfig.h
new file mode 100644
index 0000000000..844c2df8a2
--- /dev/null
+++ b/gst/gstconfig.h
@@ -0,0 +1,32 @@
+/* This header interprets the various GST_* macros that are typically *
+ * provided by the gstreamer-config or gstreamer.pc files. */
+
+#ifndef __GST_CONFIG_H__
+#define __GST_CONFIG_H__
+
+
+/***** We include config.h in case someone perhaps used a gstreamer.m4 or
+ something else that provides funky overrides. BEWARE! *****/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+
+/***** Deal with XML stuff, we have to handle both loadsave and registry *****/
+
+#if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) )
+ #include
+
+ // Include compatability defines: if libxml hasn't already defined these,
+ // we have an old version 1.x
+ #ifndef xmlChildrenNode
+ #define xmlChildrenNode childs
+ #define xmlRootNode root
+ #endif
+
+#else
+ #define GST_DISABLE_LOADSAVE_REGISTRY
+#endif
+
+#endif /* __GST_CONFIG_H__ */
diff --git a/gst/gstdata.h b/gst/gstdata.h
new file mode 100644
index 0000000000..198ae7e822
--- /dev/null
+++ b/gst/gstdata.h
@@ -0,0 +1,46 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstdata.h: Header for GstData objects (used for data passing)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_DATA_H__
+#define __GST_DATA_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define GST_DATA(data) (GstData*)(data)
+#define GST_DATA_TYPE(data) (((GstData*)(data))->type)
+
+typedef struct _GstData GstData;
+
+struct _GstData {
+ GType type;
+};
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GST_DATA_H__ */
diff --git a/gst/gstelement.c b/gst/gstelement.c
index e945f406b3..332c91be6e 100644
--- a/gst/gstelement.c
+++ b/gst/gstelement.c
@@ -65,13 +65,14 @@ static xmlNodePtr gst_element_save_thyself (GstObject *object, xmlNodePtr paren
GstElement* gst_element_restore_thyself (xmlNodePtr self, GstObject *parent);
#endif
+GType _gst_element_type = 0;
+
static GstObjectClass *parent_class = NULL;
static guint gst_element_signals[LAST_SIGNAL] = { 0 };
-GType gst_element_get_type(void) {
- static GType element_type = 0;
-
- if (!element_type) {
+GType gst_element_get_type (void)
+{
+ if (!_gst_element_type) {
static const GTypeInfo element_info = {
sizeof(GstElementClass),
(GBaseInitFunc)gst_element_base_class_init,
@@ -84,9 +85,9 @@ GType gst_element_get_type(void) {
(GInstanceInitFunc)gst_element_init,
NULL
};
- element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement", &element_info, G_TYPE_FLAG_ABSTRACT);
+ _gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement", &element_info, G_TYPE_FLAG_ABSTRACT);
}
- return element_type;
+ return _gst_element_type;
}
static void
@@ -602,14 +603,14 @@ gst_element_get_padtemplate_by_compatible (GstElement *element, GstPadTemplate *
}
static GstPad*
-gst_element_request_pad (GstElement *element, GstPadTemplate *templ)
+gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
{
GstPad *newpad = NULL;
GstElementClass *oclass;
oclass = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS(element));
if (oclass->request_new_pad)
- newpad = (oclass->request_new_pad)(element, templ);
+ newpad = (oclass->request_new_pad)(element, templ, name);
return newpad;
}
@@ -638,7 +639,7 @@ gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
templ_new = gst_element_get_padtemplate_by_compatible (element, templ);
if (templ_new != NULL)
- pad = gst_element_request_pad (element, templ_new);
+ pad = gst_element_request_pad (element, templ_new, NULL);
return pad;
}
@@ -658,19 +659,40 @@ gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
GstPad*
gst_element_request_pad_by_name (GstElement *element, const gchar *name)
{
- GstPadTemplate *templ;
+ GstPadTemplate *templ = NULL;
GstPad *pad;
+ const gchar *req_name = NULL;
+ gboolean templ_found = FALSE;
+ GList *list;
+ gint n;
g_return_val_if_fail (element != NULL, NULL);
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
g_return_val_if_fail (name != NULL, NULL);
- templ = gst_element_get_padtemplate_by_name (element, name);
+ if (strstr (name, "%d")) {
+ templ = gst_element_get_padtemplate_by_name (element, name);
+ req_name = NULL;
+ } else {
+ list = gst_element_get_padtemplate_list(element);
+ while (!templ_found && list) {
+ templ = (GstPadTemplate*) list->data;
+ if (strstr (templ->name_template, "%d")) {
+ if (sscanf(name, templ->name_template, &n)) {
+ templ_found = TRUE;
+ req_name = name;
+ break;
+ }
+ }
+ list = list->next;
+ }
+ }
+
if (templ == NULL)
- return NULL;
-
- pad = gst_element_request_pad (element, templ);
-
+ return NULL;
+
+ pad = gst_element_request_pad (element, templ, req_name);
+
return pad;
}
@@ -772,6 +794,14 @@ gst_element_error (GstElement *element, const gchar *error)
}
+GstElementState
+gst_element_get_state (GstElement *elem)
+{
+ g_return_val_if_fail (GST_IS_ELEMENT (elem), GST_STATE_VOID_PENDING);
+
+ return GST_STATE (elem);
+}
+
/**
* gst_element_set_state:
* @element: element to change state of
@@ -836,7 +866,6 @@ gst_element_set_state (GstElement *element, GstElementState state)
}
}
- /* this is redundant, really, it will always return SUCCESS */
return return_val;
}
@@ -1157,7 +1186,7 @@ gst_element_restore_thyself (xmlNodePtr self, GstObject *parent)
return element;
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE */
/**
* gst_element_set_sched:
diff --git a/gst/gstelement.h b/gst/gstelement.h
index 22d218b8e5..1d05451878 100644
--- a/gst/gstelement.h
+++ b/gst/gstelement.h
@@ -24,14 +24,7 @@
#ifndef __GST_ELEMENT_H__
#define __GST_ELEMENT_H__
-#include // NOTE: this is xml-config's fault
-
-// Include compatability defines: if libxml hasn't already defined these,
-// we have an old version 1.x
-#ifndef xmlChildrenNode
-#define xmlChildrenNode childs
-#define xmlRootNode root
-#endif
+#include
#include
#include
@@ -72,16 +65,22 @@ typedef enum {
#define GST_STATE_PAUSED_TO_READY ((GST_STATE_PAUSED<<8) | GST_STATE_READY)
#define GST_STATE_READY_TO_NULL ((GST_STATE_READY<<8) | GST_STATE_NULL)
-#define GST_TYPE_ELEMENT \
- (gst_element_get_type())
-#define GST_ELEMENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ELEMENT,GstElement))
-#define GST_ELEMENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ELEMENT,GstElementClass))
-#define GST_IS_ELEMENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ELEMENT))
-#define GST_IS_ELEMENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT))
+extern GType _gst_element_type;
+
+#define GST_TYPE_ELEMENT (_gst_element_type)
+
+#define GST_ELEMENT_FAST(obj) ((GstElement*)(obj))
+#define GST_ELEMENT_CLASS_FAST(klass) ((GstElementClass*)(klass))
+#define GST_IS_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_ELEMENT))
+#define GST_IS_ELEMENT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_ELEMENT))
+
+#ifdef GST_TYPE_PARANOID
+# define GST_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_ELEMENT, GstElement))
+# define GST_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_ELEMENT, GstElementClass))
+#else
+# define GST_ELEMENT GST_ELEMENT_FAST
+# define GST_ELEMENT_CLASS GST_ELEMENT_CLASS_FAST
+#endif
typedef enum {
/* element is complex (for some def.) and generally require a cothread */
@@ -132,32 +131,32 @@ typedef struct _GstElementFactoryClass GstElementFactoryClass;
typedef void (*GstElementLoopFunction) (GstElement *element);
struct _GstElement {
- GstObject object;
-
- guint8 current_state;
- guint8 pending_state;
+ GstObject object;
+ /* element state and scheduling */
+ guint8 current_state;
+ guint8 pending_state;
+ GstElement *manager;
+ GstSchedule *sched;
GstElementLoopFunction loopfunc;
- cothread_state *threadstate;
- GstPad *select_pad;
+ cothread_state *threadstate;
- guint16 numpads;
- guint16 numsrcpads;
- guint16 numsinkpads;
- GList *pads;
-
- GstElement *manager;
- GstSchedule *sched;
+ /* element pads */
+ guint16 numpads;
+ guint16 numsrcpads;
+ guint16 numsinkpads;
+ GList *pads;
+ GstPad *select_pad;
};
struct _GstElementClass {
- GstObjectClass parent_class;
+ GstObjectClass parent_class;
/* the elementfactory that created us */
- GstElementFactory *elementfactory;
+ GstElementFactory *elementfactory;
/* templates for our pads */
- GList *padtemplates;
- gint numpadtemplates;
+ GList *padtemplates;
+ gint numpadtemplates;
/* signal callbacks */
void (*state_change) (GstElement *element,GstElementState state);
@@ -169,13 +168,13 @@ struct _GstElementClass {
void (*eos) (GstElement *element);
/* local pointers for get/set */
- void (*set_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
- void (*get_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+ void (*set_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+ void (*get_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
/* change the element state */
GstElementStateReturn (*change_state) (GstElement *element);
/* request a new pad */
- GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ);
+ GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ, const gchar* name);
};
void gst_element_class_add_padtemplate (GstElementClass *element, GstPadTemplate *templ);
@@ -215,6 +214,7 @@ void gst_element_disconnect (GstElement *src, const gchar *srcpadname,
void gst_element_signal_eos (GstElement *element);
+GstElementState gst_element_get_state (GstElement *elem);
/* called by the app to set the state of the element */
gint gst_element_set_state (GstElement *element, GstElementState state);
const gchar * gst_element_statename (GstElementState state);
@@ -223,8 +223,10 @@ void gst_element_error (GstElement *element, const gchar *error);
GstElementFactory* gst_element_get_factory (GstElement *element);
+#ifndef GST_DISABLE_LOADSAVE
/* XML write and read */
GstElement* gst_element_restore_thyself (xmlNodePtr self, GstObject *parent);
+#endif
/*
@@ -243,16 +245,13 @@ struct _GstElementDetails {
gchar *copyright; /* copyright details (year, etc.) */
};
-#define GST_TYPE_ELEMENTFACTORY \
- (gst_elementfactory_get_type())
-#define GST_ELEMENTFACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ELEMENTFACTORY,GstElementFactory))
-#define GST_ELEMENTFACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ELEMENTFACTORY,GstElementFactoryClass))
-#define GST_IS_ELEMENTFACTORY(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ELEMENTFACTORY))
-#define GST_IS_ELEMENTFACTORY_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENTFACTORY))
+#define GST_TYPE_ELEMENTFACTORY (gst_elementfactory_get_type())
+#define GST_ELEMENTFACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ELEMENTFACTORY,\
+ GstElementFactory))
+#define GST_ELEMENTFACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ELEMENTFACTORY,\
+ GstElementFactoryClass))
+#define GST_IS_ELEMENTFACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ELEMENTFACTORY))
+#define GST_IS_ELEMENTFACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENTFACTORY))
struct _GstElementFactory {
GstPluginFeature feature;
diff --git a/gst/gstelementfactory.c b/gst/gstelementfactory.c
index 8ecc553db5..0f4dde38c0 100644
--- a/gst/gstelementfactory.c
+++ b/gst/gstelementfactory.c
@@ -31,7 +31,7 @@ static void gst_elementfactory_init (GstElementFactory *factory);
#ifndef GST_DISABLE_REGISTRY
static void gst_elementfactory_restore_thyself (GstObject *object, xmlNodePtr parent);
static xmlNodePtr gst_elementfactory_save_thyself (GstObject *object, xmlNodePtr parent);
-#endif /* GST_DISABLE_REGISTRY */
+#endif
static void gst_elementfactory_unload_thyself (GstPluginFeature *feature);
@@ -81,7 +81,7 @@ gst_elementfactory_class_init (GstElementFactoryClass *klass)
#ifndef GST_DISABLE_REGISTRY
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_elementfactory_save_thyself);
gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_elementfactory_restore_thyself);
-#endif /* GST_DISABLE_REGISTRY */
+#endif
gstpluginfeature_class->unload_thyself = GST_DEBUG_FUNCPTR (gst_elementfactory_unload_thyself);
diff --git a/gst/gstevent.c b/gst/gstevent.c
new file mode 100644
index 0000000000..10aa9c3ca0
--- /dev/null
+++ b/gst/gstevent.c
@@ -0,0 +1,96 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstevent.h: Header for GstEvent subsystem
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#include "gst/gstinfo.h"
+#include "gst/gstevent.h"
+
+GType _gst_event_type;
+
+static GMemChunk *_gst_event_chunk;
+static GMutex *_gst_event_chunk_lock;
+
+void
+_gst_event_initialize (void)
+{
+ gint eventsize = sizeof(GstEvent);
+ static const GTypeInfo event_info = {
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL,
+ };
+
+ // round up to the nearest 32 bytes for cache-line and other efficiencies
+ eventsize = (((eventsize-1) / 32) + 1) * 32;
+
+ _gst_event_chunk = g_mem_chunk_new ("GstEvent", eventsize,
+ eventsize * 32, G_ALLOC_AND_FREE);
+
+ _gst_event_chunk_lock = g_mutex_new ();
+
+ // register the type
+ _gst_event_type = g_type_register_static (G_TYPE_INT, "GstEvent", &event_info, 0);
+}
+
+GstEvent*
+gst_event_new (GstEventType type)
+{
+ GstEvent *event;
+
+ g_mutex_lock (_gst_event_chunk_lock);
+ event = g_mem_chunk_alloc (_gst_event_chunk);
+ g_mutex_unlock (_gst_event_chunk_lock);
+ GST_INFO (GST_CAT_EVENT, "creating new event %p", event);
+
+ GST_DATA_TYPE (event) = _gst_event_type;
+ GST_EVENT_TYPE (event) = type;
+
+ return event;
+}
+
+void
+gst_event_free (GstEvent* event)
+{
+ g_mutex_lock (_gst_event_chunk_lock);
+ g_mem_chunk_free (_gst_event_chunk, event);
+ g_mutex_unlock (_gst_event_chunk_lock);
+}
+
+/* seek stuff */
+GstEvent*
+gst_event_new_seek (GstSeekType type, guint64 offset, gboolean flush)
+{
+ GstEvent *event;
+
+ event = gst_event_new (GST_EVENT_SEEK);
+ GST_EVENT_SEEK_TYPE (event) = type;
+ GST_EVENT_SEEK_OFFSET (event) = offset;
+ GST_EVENT_SEEK_FLUSH (event) = flush;
+
+ return event;
+}
diff --git a/gst/gstevent.h b/gst/gstevent.h
index 0b5b13402c..2e45b2b855 100644
--- a/gst/gstevent.h
+++ b/gst/gstevent.h
@@ -25,6 +25,7 @@
#define __GST_EVENT_H__
#include
+#include
#ifdef __cplusplus
extern "C" {
@@ -36,14 +37,57 @@ typedef enum {
GST_EVENT_FLUSH,
GST_EVENT_EMPTY,
GST_EVENT_SEEK,
+ GST_EVENT_DISCONTINUOUS
} GstEventType;
+extern GType _gst_event_type;
+
+#define GST_TYPE_EVENT (_gst_event_type)
+#define GST_EVENT(event) ((GstEvent*)(event))
+#define GST_IS_EVENT(event) (GST_DATA_TYPE(event) == GST_TYPE_EVENT)
+
+#define GST_EVENT_TYPE(event) (GST_EVENT(event)->type)
+#define GST_EVENT_TIMESTAMP(event) (GST_EVENT(event)->timstamp)
+
+/* seek events */
+typedef enum {
+ GST_SEEK_ANY,
+ GST_SEEK_TIMEOFFSET,
+ GST_SEEK_BYTEOFFSET
+} GstSeekType;
+
+#define GST_EVENT_SEEK_TYPE(event) (GST_EVENT(event)->event_data.seek.type)
+#define GST_EVENT_SEEK_OFFSET(event) (GST_EVENT(event)->event_data.seek.offset)
+#define GST_EVENT_SEEK_FLUSH(event) (GST_EVENT(event)->event_data.seek.flush)
+
typedef struct _GstEvent GstEvent;
struct _GstEvent {
- GstEventType type;
+ GstData data;
+
+ GstEventType type;
+ guint64 timestamp;
+
+ union {
+ struct {
+ GstSeekType type;
+ guint64 offset;
+ gboolean flush;
+ } seek;
+ } event_data;
};
+void _gst_event_initialize (void);
+
+GstEvent* gst_event_new (GstEventType type);
+void gst_event_free (GstEvent* event);
+
+/* seek events */
+GstEvent* gst_event_new_seek (GstSeekType type, guint64 offset, gboolean flush);
+
+/* flush events */
+#define gst_event_new_flush() gst_event_new(GST_EVENT_FLUSH)
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gst/gstinfo.c b/gst/gstinfo.c
index 3518ec2ecb..ea63ea630e 100644
--- a/gst/gstinfo.c
+++ b/gst/gstinfo.c
@@ -459,6 +459,8 @@ gst_default_error_handler (gchar *file, gchar *function,
/***** DEBUG system *****/
GHashTable *__gst_function_pointers = NULL;
+// FIXME make this thread specific
+static GSList* stack_trace = NULL;
gchar *_gst_debug_nameof_funcptr (void *ptr) __attribute__ ((no_instrument_function));
@@ -479,15 +481,52 @@ _gst_debug_nameof_funcptr (void *ptr)
#ifdef GST_ENABLE_FUNC_INSTRUMENTATION
-
void __cyg_profile_func_enter(void *this_fn,void *call_site) __attribute__ ((no_instrument_function));
-void __cyg_profile_func_enter(void *this_fn,void *call_site) {
- GST_DEBUG(GST_CAT_CALL_TRACE, "entering function %s\n", _gst_debug_nameof_funcptr (this_fn));
+void __cyg_profile_func_enter(void *this_fn,void *call_site)
+{
+ gchar *name = _gst_debug_nameof_funcptr (this_fn);
+ gchar *site = _gst_debug_nameof_funcptr (call_site);
+
+ GST_DEBUG(GST_CAT_CALL_TRACE, "entering function %s from %s\n", name, site);
+ stack_trace = g_slist_prepend (stack_trace, g_strdup_printf ("%8p in %s from %p (%s)", this_fn, name, call_site, site));
+
+ g_free (name);
+ g_free (site);
}
void __cyg_profile_func_exit(void *this_fn,void *call_site) __attribute__ ((no_instrument_function));
-void __cyg_profile_func_exit(void *this_fn,void *call_site) {
- GST_DEBUG(GST_CAT_CALL_TRACE, "leavinging function %s\n", _gst_debug_nameof_funcptr (this_fn));
+void __cyg_profile_func_exit(void *this_fn,void *call_site)
+{
+ gchar *name = _gst_debug_nameof_funcptr (this_fn);
+
+ GST_DEBUG(GST_CAT_CALL_TRACE, "leaving function %s\n", name);
+ g_free (stack_trace->data);
+ stack_trace = g_slist_delete_link (stack_trace, stack_trace);
+
+ g_free (name);
+}
+
+void
+gst_debug_print_stack_trace (void)
+{
+ GSList *walk = stack_trace;
+ gint count = 0;
+
+ if (walk)
+ walk = g_slist_next (walk);
+
+ while (walk) {
+ gchar *name = (gchar *) walk->data;
+
+ g_print ("#%-2d %s\n", count++, name);
+
+ walk = g_slist_next (walk);
+ }
+}
+#else
+void
+gst_debug_print_stack_trace (void)
+{
}
#endif /* GST_ENABLE_FUNC_INTSTRUMENTATION */
diff --git a/gst/gstinfo.h b/gst/gstinfo.h
index f5c06bd5f2..4f3f605d7c 100644
--- a/gst/gstinfo.h
+++ b/gst/gstinfo.h
@@ -341,6 +341,8 @@ _gst_debug_register_funcptr (void *ptr, gchar *ptrname)
gchar *_gst_debug_nameof_funcptr (void *ptr);
+void gst_debug_print_stack_trace (void);
+
#endif /* __GSTINFO_H__ */
diff --git a/gst/gstobject.c b/gst/gstobject.c
index 3e8d0b9434..70d81227c3 100644
--- a/gst/gstobject.c
+++ b/gst/gstobject.c
@@ -27,7 +27,7 @@
/* Object signals and args */
enum {
PARENT_SET,
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
OBJECT_SAVED,
#endif
LAST_SIGNAL
@@ -43,6 +43,8 @@ enum {
SO_LAST_SIGNAL
};
+GType _gst_object_type = 0;
+
typedef struct _GstSignalObject GstSignalObject;
typedef struct _GstSignalObjectClass GstSignalObjectClass;
@@ -64,9 +66,7 @@ static guint gst_object_signals[LAST_SIGNAL] = { 0 };
GType
gst_object_get_type (void)
{
- static GType object_type = 0;
-
- if (!object_type) {
+ if (!_gst_object_type) {
static const GTypeInfo object_info = {
sizeof (GstObjectClass),
NULL,
@@ -79,9 +79,9 @@ gst_object_get_type (void)
(GInstanceInitFunc) gst_object_init,
NULL
};
- object_type = g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, G_TYPE_FLAG_ABSTRACT);
+ _gst_object_type = g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, G_TYPE_FLAG_ABSTRACT);
}
- return object_type;
+ return _gst_object_type;
}
static void
@@ -98,7 +98,7 @@ gst_object_class_init (GstObjectClass *klass)
G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,G_TYPE_NONE,1,
G_TYPE_OBJECT);
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
gst_object_signals[OBJECT_SAVED] =
g_signal_new("object_saved", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL, NULL,
@@ -446,7 +446,7 @@ gst_object_check_uniqueness (GList *list, const gchar *name)
}
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
/**
* gst_object_save_thyself:
* @object: GstObject to save
@@ -496,7 +496,7 @@ gst_object_restore_thyself (GstObject *object, xmlNodePtr parent)
if (oclass->restore_thyself)
oclass->restore_thyself (object, parent);
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
/**
* gst_object_get_path_string:
@@ -577,9 +577,9 @@ struct _GstSignalObjectClass {
GObjectClass parent_class;
/* signals */
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
void (*object_loaded) (GstSignalObject *object, GstObject *new, xmlNodePtr self);
-#endif /* GST_DISABLE_LOADSAVE */
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
};
static GType
@@ -614,7 +614,7 @@ gst_signal_object_class_init (GstSignalObjectClass *klass)
parent_class = g_type_class_ref (G_TYPE_OBJECT);
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
gst_signal_object_signals[SO_OBJECT_LOADED] =
g_signal_new("object_loaded", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
@@ -648,7 +648,7 @@ gst_class_signal_connect (GstObjectClass *klass,
return g_signal_connect (klass->signal_object, name, func, func_data);
}
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
/**
* gst_class_signal_emit_by_name:
* @object: the object that sends the signal
@@ -669,4 +669,4 @@ gst_class_signal_emit_by_name (GstObject *object,
g_signal_emit_by_name (oclass->signal_object, name, object, self);
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
diff --git a/gst/gstobject.h b/gst/gstobject.h
index d8140c7ac6..681dcadde4 100644
--- a/gst/gstobject.h
+++ b/gst/gstobject.h
@@ -24,10 +24,7 @@
#ifndef __GST_OBJECT_H__
#define __GST_OBJECT_H__
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
+#include
#ifdef USE_GLIB2
#include // note that this gets wrapped in __GST_OBJECT_H__
@@ -36,15 +33,13 @@
#include
#endif
-#include
-#include
-
-#include
-
#ifdef HAVE_ATOMIC_H
#include
#endif
+#include
+#include
+
// FIXME
#include "gstlog.h"
@@ -52,17 +47,22 @@
extern "C" {
#endif /* __cplusplus */
+extern GType _gst_object_type;
-#define GST_TYPE_OBJECT \
- (gst_object_get_type())
-#define GST_OBJECT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OBJECT,GstObject))
-#define GST_OBJECT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OBJECT,GstObjectClass))
-#define GST_IS_OBJECT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OBJECT))
-#define GST_IS_OBJECT_CLASS(obj) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OBJECT))
+#define GST_TYPE_OBJECT (_gst_object_type)
+# define GST_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OBJECT))
+# define GST_IS_OBJECT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OBJECT))
+
+#define GST_OBJECT_FAST(obj) ((GstObject*)(obj))
+#define GST_OBJECT_CLASS_FAST(klass) ((GstObjectClass*)(klass))
+
+#ifdef GST_TYPE_PARANOID
+# define GST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OBJECT, GstObject))
+# define GST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OBJECT, GstObjectClass))
+#else
+# define GST_OBJECT GST_OBJECT_FAST
+# define GST_OBJECT_CLASS GST_OBJECT_CLASS_FAST
+#endif
//typedef struct _GstObject GstObject;
//typedef struct _GstObjectClass GstObjectClass;
@@ -76,40 +76,43 @@ typedef enum
} GstObjectFlags;
struct _GstObject {
- GObject object;
+ GObject object;
- gchar *name;
+ gchar *name;
/* have to have a refcount for the object */
#ifdef HAVE_ATOMIC_H
- atomic_t refcount;
+ atomic_t refcount;
#else
- int refcount;
+ gint refcount;
#endif
/* locking for all sorts of things (like the refcount) */
- GMutex *lock;
-
+ GMutex *lock;
/* this objects parent */
- GstObject *parent;
+ GstObject *parent;
- guint32 flags;
+ guint32 flags;
};
struct _GstObjectClass {
GObjectClass parent_class;
- gchar *path_string_separator;
- GObject *signal_object;
+ gchar *path_string_separator;
+ GObject *signal_object;
/* signals */
void (*parent_set) (GstObject *object, GstObject *parent);
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
void (*object_saved) (GstObject *object, xmlNodePtr parent);
+#endif
/* functions go here */
void (*destroy) (GstObject *object);
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
xmlNodePtr (*save_thyself) (GstObject *object, xmlNodePtr parent);
void (*restore_thyself) (GstObject *object, xmlNodePtr self);
+#endif
};
#define GST_FLAGS(obj) (GST_OBJECT (obj)->flags)
@@ -144,11 +147,12 @@ void gst_object_unparent (GstObject *object);
gboolean gst_object_check_uniqueness (GList *list, const gchar *name);
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
xmlNodePtr gst_object_save_thyself (GstObject *object, xmlNodePtr parent);
-void gst_object_restore_thyself (GstObject *object, xmlNodePtr parent);
+void gst_object_restore_thyself (GstObject *object, xmlNodePtr parent);
#else
#pragma GCC poison gst_object_save_thyself
+#pragma GCC poison gst_object_restore_thyself
#endif
/* refcounting */
@@ -166,7 +170,7 @@ guint gst_class_signal_connect (GstObjectClass *klass,
gpointer func,
gpointer func_data);
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
void gst_class_signal_emit_by_name (GstObject *object,
const gchar *name,
xmlNodePtr self);
diff --git a/gst/gstpad.c b/gst/gstpad.c
index a21a96415f..c5c985d025 100644
--- a/gst/gstpad.c
+++ b/gst/gstpad.c
@@ -30,6 +30,7 @@
#include "gstbin.h"
#include "gstscheduler.h"
+GType _gst_pad_type = 0;
/***** Start with the base GstPad class *****/
static void gst_pad_class_init (GstPadClass *klass);
@@ -42,10 +43,9 @@ static xmlNodePtr gst_pad_save_thyself (GstObject *object, xmlNodePtr parent);
static GstObject *pad_parent_class = NULL;
GType
-gst_pad_get_type(void) {
- static GType pad_type = 0;
-
- if (!pad_type) {
+gst_pad_get_type(void)
+{
+ if (!_gst_pad_type) {
static const GTypeInfo pad_info = {
sizeof(GstPadClass),
NULL,
@@ -58,9 +58,9 @@ gst_pad_get_type(void) {
(GInstanceInitFunc)gst_pad_init,
NULL
};
- pad_type = g_type_register_static(GST_TYPE_OBJECT, "GstPad", &pad_info, 0);
+ _gst_pad_type = g_type_register_static(GST_TYPE_OBJECT, "GstPad", &pad_info, 0);
}
- return pad_type;
+ return _gst_pad_type;
}
static void
@@ -107,15 +107,14 @@ static void gst_real_pad_dispose (GObject *object);
static void gst_pad_push_func (GstPad *pad, GstBuffer *buf);
+GType _gst_real_pad_type = 0;
static GstPad *real_pad_parent_class = NULL;
static guint gst_real_pad_signals[REAL_LAST_SIGNAL] = { 0 };
GType
gst_real_pad_get_type(void) {
- static GType pad_type = 0;
-
- if (!pad_type) {
+ if (!_gst_real_pad_type) {
static const GTypeInfo pad_info = {
sizeof(GstRealPadClass),
NULL,
@@ -128,9 +127,9 @@ gst_real_pad_get_type(void) {
(GInstanceInitFunc)gst_real_pad_init,
NULL
};
- pad_type = g_type_register_static(GST_TYPE_PAD, "GstRealPad", &pad_info, 0);
+ _gst_real_pad_type = g_type_register_static(GST_TYPE_PAD, "GstRealPad", &pad_info, 0);
}
- return pad_type;
+ return _gst_real_pad_type;
}
static void
@@ -1432,7 +1431,7 @@ gst_pad_ghost_save_thyself (GstPad *pad,
return self;
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE */
#ifndef gst_pad_push
/**
@@ -1881,6 +1880,7 @@ gst_pad_get_element_private (GstPad *pad)
/***** ghost pads *****/
+GType _gst_ghost_pad_type = 0;
static void gst_ghost_pad_class_init (GstGhostPadClass *klass);
static void gst_ghost_pad_init (GstGhostPad *pad);
@@ -1890,9 +1890,7 @@ static GstPad *ghost_pad_parent_class = NULL;
GType
gst_ghost_pad_get_type(void) {
- static GType pad_type = 0;
-
- if (!pad_type) {
+ if (!_gst_ghost_pad_type) {
static const GTypeInfo pad_info = {
sizeof(GstGhostPadClass),
NULL,
@@ -1905,9 +1903,9 @@ gst_ghost_pad_get_type(void) {
(GInstanceInitFunc)gst_ghost_pad_init,
NULL
};
- pad_type = g_type_register_static(GST_TYPE_PAD, "GstGhostPad", &pad_info, 0);
+ _gst_ghost_pad_type = g_type_register_static(GST_TYPE_PAD, "GstGhostPad", &pad_info, 0);
}
- return pad_type;
+ return _gst_ghost_pad_type;
}
static void
@@ -1985,14 +1983,36 @@ gst_pad_event (GstPad *pad, GstEventType event, gint64 timestamp, guint32 data)
GST_DEBUG(GST_CAT_EVENT, "have event %d on pad %s:%s\n",(gint)event,GST_DEBUG_PAD_NAME(pad));
peer = GST_RPAD_PEER(pad);
- if (GST_RPAD_EVENTFUNC(peer))
- handled = GST_RPAD_EVENTFUNC(peer) (peer, event, timestamp, data);
+ if (GST_RPAD_EVENTFUNC(peer)) {
+ //handled = GST_RPAD_EVENTFUNC(peer) (peer, event, timestamp, data);
+ }
else {
GST_DEBUG(GST_CAT_EVENT, "there's no event function for peer %s:%s\n",GST_DEBUG_PAD_NAME(peer));
}
if (!handled) {
GST_DEBUG(GST_CAT_EVENT, "would proceed with default behavior here\n");
- gst_pad_event_default(peer,event, timestamp, data);
+ //gst_pad_event_default(peer,event, timestamp, data);
}
}
+
+gboolean
+gst_pad_send_event (GstPad *pad, GstEvent *event)
+{
+ gboolean handled = FALSE;
+
+ GST_DEBUG (GST_CAT_EVENT, "have event %d on pad %s:%s\n",
+ GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
+
+ if (GST_RPAD_EVENTFUNC (pad))
+ handled = GST_RPAD_EVENTFUNC (pad) (pad, event);
+ else {
+ GST_DEBUG(GST_CAT_EVENT, "there's no event function for pad %s:%s\n", GST_DEBUG_PAD_NAME (pad));
+ }
+
+ if (!handled) {
+ GST_DEBUG(GST_CAT_EVENT, "would proceed with default behavior here\n");
+ //gst_pad_event_default (pad, event);
+ }
+}
+
diff --git a/gst/gstpad.h b/gst/gstpad.h
index cda8b229b0..70f0a39647 100644
--- a/gst/gstpad.h
+++ b/gst/gstpad.h
@@ -24,14 +24,7 @@
#ifndef __GST_PAD_H__
#define __GST_PAD_H__
-#include // NOTE: This is xml-config's fault
-
-// Include compatability defines: if libxml hasn't already defined these,
-// we have an old version 1.x
-#ifndef xmlChildrenNode
-#define xmlChildrenNode childs
-#define xmlRootNode root
-#endif
+#include
#include
#include
@@ -44,25 +37,70 @@
extern "C" {
#endif /* __cplusplus */
+extern GType _gst_pad_type;
+extern GType _gst_real_pad_type;
+extern GType _gst_ghost_pad_type;
-#define GST_TYPE_PAD (gst_pad_get_type ())
-#define GST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PAD, GstPad))
-#define GST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PAD, GstPadClass))
+//#define GST_TYPE_PARANOID
+
+/*
+ * Pad base class
+ */
+#define GST_TYPE_PAD (_gst_pad_type)
+
+#define GST_PAD_FAST(obj) ((GstPad*)(obj))
+#define GST_PAD_CLASS_FAST(klass) ((GstPadClass*)(klass))
#define GST_IS_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PAD))
+#define GST_IS_PAD_FAST(obj) (G_OBJECT_TYPE(obj) == GST_TYPE_REAL_PAD || \
+ G_OBJECT_TYPE(obj) == GST_TYPE_GHOST_PAD)
#define GST_IS_PAD_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PAD))
-#define GST_TYPE_REAL_PAD (gst_real_pad_get_type ())
-#define GST_REAL_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_REAL_PAD, GstRealPad))
-#define GST_REAL_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_REAL_PAD, GstRealPadClass))
+#ifdef GST_TYPE_PARANOID
+# define GST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PAD, GstPad))
+# define GST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PAD, GstPadClass))
+#else
+# define GST_PAD GST_PAD_FAST
+# define GST_PAD_CLASS GST_PAD_CLASS_FAST
+#endif
+
+/*
+ * Real Pads
+ */
+#define GST_TYPE_REAL_PAD (_gst_real_pad_type)
+
+#define GST_REAL_PAD_FAST(obj) ((GstRealPad*)(obj))
+#define GST_REAL_PAD_CLASS_FAST(klass) ((GstRealPadClass*)(klass))
#define GST_IS_REAL_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_REAL_PAD))
+#define GST_IS_REAL_PAD_FAST(obj) (G_OBJECT_TYPE(obj) == GST_TYPE_REAL_PAD)
#define GST_IS_REAL_PAD_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_REAL_PAD))
-#define GST_TYPE_GHOST_PAD (gst_ghost_pad_get_type ())
-#define GST_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GHOST_PAD, GstGhostPad))
-#define GST_GHOST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GHOST_PAD, GstGhostPadClass))
+#ifdef GST_TYPE_PARANOID
+# define GST_REAL_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_REAL_PAD, GstRealPad))
+# define GST_REAL_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_REAL_PAD, GstRealPadClass))
+#else
+# define GST_REAL_PAD GST_REAL_PAD_FAST
+# define GST_REAL_PAD_CLASS GST_REAL_PAD_CLASS_FAST
+#endif
+
+/*
+ * Ghost Pads
+ */
+#define GST_TYPE_GHOST_PAD (_gst_ghost_pad_type)
+
+#define GST_GHOST_PAD_FAST(obj) ((GstGhostPad*)(obj))
+#define GST_GHOST_PAD_CLASS_FAST(klass) ((GstGhostPadClass*)(klass))
#define GST_IS_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GHOST_PAD))
+#define GST_IS_GHOST_PAD_FAST(obj) (G_OBJECT_TYPE(obj) == GST_TYPE_GHOST_PAD)
#define GST_IS_GHOST_PAD_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GHOST_PAD))
+#ifdef GST_TYPE_PARANOID
+# define GST_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GHOST_PAD, GstGhostPad))
+# define GST_GHOST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GHOST_PAD, GstGhostPadClass))
+#else
+# define GST_GHOST_PAD GST_GHOST_PAD_FAST
+# define GST_GHOST_PAD_CLASS GST_GHOST_PAD_CLASS_FAST
+#endif
+
//typedef struct _GstPad GstPad;
//typedef struct _GstPadClass GstPadClass;
@@ -92,7 +130,7 @@ typedef enum {
* buf is the buffer being passed */
typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
typedef GstBuffer* (*GstPadGetFunction) (GstPad *pad);
-typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEventType event, gint64 timestamp, guint32 data);
+typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
typedef GstBuffer* (*GstPadGetRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
typedef GstBuffer* (*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
@@ -375,12 +413,15 @@ FALSE )
}G_STMT_END
#endif
+gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
GstBuffer* gst_pad_peek (GstPad *pad);
GstPad* gst_pad_select (GList *padlist);
GstPad* gst_pad_selectv (GstPad *pad, ...);
+#ifndef GST_DISABLE_LOADSAVE
void gst_pad_load_and_connect (xmlNodePtr self, GstObject *parent);
+#endif
/* ghostpads */
@@ -397,8 +438,10 @@ GstPadTemplate* gst_padtemplate_new (gchar *name_template,
GstCaps* gst_padtemplate_get_caps (GstPadTemplate *templ);
GstCaps* gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name);
+#ifndef GST_DISABLE_LOADSAVE
xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent);
GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent);
+#endif
xmlNodePtr gst_pad_ghost_save_thyself (GstPad *pad,
GstElement *bin,
diff --git a/gst/gstparse.c b/gst/gstparse.c
index cf7fc1ff1f..b7e519175a 100644
--- a/gst/gstparse.c
+++ b/gst/gstparse.c
@@ -299,7 +299,11 @@ gst_parse_launch_cmdline(int argc,char *argv[],GstBin *parent,gst_parse_priv *pr
element = gst_elementfactory_make(arg,ptr);
g_free(ptr);
if (!element) {
+#ifndef GST_DISABLE_REGISTRY
fprintf(stderr,"Couldn't create a '%s', no such element or need to run gstreamer-register?\n",arg);
+#else
+ fprintf(stderr,"Couldn't create a '%s', no such element or need to load pluginn?\n",arg);
+#endif
exit(-1);
}
GST_DEBUG(0,"CREATED element %s\n",GST_ELEMENT_NAME(element));
diff --git a/gst/gstplugin.c b/gst/gstplugin.c
index a540a77b4b..9f1f1408b2 100644
--- a/gst/gstplugin.c
+++ b/gst/gstplugin.c
@@ -105,7 +105,7 @@ _gst_plugin_initialize (void)
gst_plugin_load_thyself (doc->xmlRootNode);
xmlFreeDoc (doc);
-#endif // GST_DISABLE_REGISTRY
+#endif /* GST_DISABLE_REGISTRY */
}
void
@@ -845,7 +845,7 @@ gst_plugin_load_thyself (xmlNodePtr parent)
}
GST_INFO (GST_CAT_PLUGIN_LOADING, "added %d features ", featurecount);
}
-#endif // GST_DISABLE_REGISTRY
+#endif /* GST_DISABLE_REGISTRY */
/**
diff --git a/gst/gstplugin.h b/gst/gstplugin.h
index e678f58a3b..58eb018f2e 100644
--- a/gst/gstplugin.h
+++ b/gst/gstplugin.h
@@ -24,15 +24,9 @@
#ifndef __GST_PLUGIN_H__
#define __GST_PLUGIN_H__
-#include
-#include // NOTE: this is xml-config's fault
+#include
-// Include compatability defines: if libxml hasn't already defined these,
-// we have an old version 1.x
-#ifndef xmlChildrenNode
-#define xmlChildrenNode childs
-#define xmlRootNode root
-#endif
+#include
#include
diff --git a/gst/gstprops.c b/gst/gstprops.c
index 037eb304dc..670498d283 100644
--- a/gst/gstprops.c
+++ b/gst/gstprops.c
@@ -987,7 +987,7 @@ end:
return compatible;
}
-#if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) )
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
static xmlNodePtr
gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
{
@@ -1242,5 +1242,5 @@ gst_props_load_thyself (xmlNodePtr parent)
return props;
}
-#endif /* (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) ) */
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
diff --git a/gst/gstprops.h b/gst/gstprops.h
index 1d7730994a..9fc6dce2e3 100644
--- a/gst/gstprops.h
+++ b/gst/gstprops.h
@@ -24,16 +24,9 @@
#ifndef __GST_PROPS_H__
#define __GST_PROPS_H__
+#include
+
#include
-#include // NOTE: this is xml-config's fault
-
-// Include compatability defines: if libxml hasn't already defined these,
-// we have an old version 1.x
-#ifndef xmlChildrenNode
-#define xmlChildrenNode childs
-#define xmlRootNode root
-#endif
-
typedef struct _GstProps GstProps;
@@ -95,7 +88,9 @@ gulong gst_props_get_fourcc_int (GstProps *props, const gchar *name);
gboolean gst_props_get_boolean (GstProps *props, const gchar *name);
const gchar* gst_props_get_string (GstProps *props, const gchar *name);
+#ifndef GST_DISABLE_LOADSAVE
xmlNodePtr gst_props_save_thyself (GstProps *props, xmlNodePtr parent);
GstProps* gst_props_load_thyself (xmlNodePtr parent);
+#endif
#endif /* __GST_PROPS_H__ */
diff --git a/gst/gstscheduler.c b/gst/gstscheduler.c
index b24012d9f0..fc4abe0a72 100644
--- a/gst/gstscheduler.c
+++ b/gst/gstscheduler.c
@@ -1424,7 +1424,7 @@ GST_DEBUG(GST_CAT_SCHEDULING,"there are %d elements in this chain\n",chain->num_
}
} else {
GST_INFO (GST_CAT_DATAFLOW,"NO ENABLED ELEMENTS IN CHAIN!!");
- //eos = TRUE;
+ eos = TRUE;
}
/*
diff --git a/gst/gstthread.c b/gst/gstthread.c
index 322c91b223..27ae96c6d7 100644
--- a/gst/gstthread.c
+++ b/gst/gstthread.c
@@ -124,16 +124,16 @@ gst_thread_class_init (GstThreadClass *klass)
gobject_class->dispose = gst_thread_dispose;
#ifndef GST_DISABLE_LOADSAVE
- gstobject_class->save_thyself = gst_thread_save_thyself;
- gstobject_class->restore_thyself = gst_thread_restore_thyself;
+ gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_thread_save_thyself);
+ gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR(gst_thread_restore_thyself);
#endif
- gstelement_class->change_state = gst_thread_change_state;
+ gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_thread_change_state);
// gstbin_class->schedule = gst_thread_schedule_dummy;
- gobject_class->set_property = gst_thread_set_property;
- gobject_class->get_property = gst_thread_get_property;
+ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_thread_set_property);
+ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_thread_get_property);
}
diff --git a/gst/gstversion.h.in b/gst/gstversion.h.in
index 820e7fc7f7..0cfd4dbe25 100644
--- a/gst/gstversion.h.in
+++ b/gst/gstversion.h.in
@@ -28,4 +28,6 @@
#define GST_VERSION_MINOR @GST_VERSION_MINOR@
#define GST_VERSION_MICRO @GST_VERSION_MICRO@
+void gst_version (guint *major, guint *minor, guint *micro);
+
#endif /* __GST_H__ */
diff --git a/gst/gstxml.h b/gst/gstxml.h
index f3fd8d0437..b66aba2608 100644
--- a/gst/gstxml.h
+++ b/gst/gstxml.h
@@ -23,17 +23,10 @@
#ifndef __GST_XML_H__
#define __GST_XML_H__
+#include
+
#ifndef GST_DISABLE_LOADSAVE
-#include
-
-// Include compatability defines: if libxml hasn't already defined these,
-// we have an old version 1.x
-#ifndef xmlChildrenNode
-#define xmlChildrenNode childs
-#define xmlRootNode root
-#endif
-
#include
#ifdef __cplusplus
diff --git a/gst/utils/gstbytestream.c b/gst/utils/gstbytestream.c
new file mode 100644
index 0000000000..5cc36639ce
--- /dev/null
+++ b/gst/utils/gstbytestream.c
@@ -0,0 +1,113 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstbytestreams.c: Utility functions: gtk_get_property stuff, etc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include
+#include
+
+#include "gstbytestreams.h"
+
+/**
+ * gst_bytestream_new:
+ * @pad: the pad to attach the bytstream to
+ *
+ * creates a bytestream from the given pad
+ *
+ * Returns: a new #GstByteStream object
+ */
+GstByteStream *
+gst_bytestream_new (GstPad * pad)
+{
+ GstByteStream *bs = g_new (GstByteStream, 1);
+
+ bs->pad = pad;
+ bs->data = NULL;
+ bs->size = 0;
+ bs->index = 0;
+
+ return bs;
+}
+
+void
+gst_bytestream_destroy (GstByteStream * bs)
+{
+ if (bs->data) {
+ g_free (bs->data);
+ }
+ g_free (bs);
+}
+
+static void
+gst_bytestream_bytes_fill (GstByteStream * bs, guint64 len)
+{
+ size_t oldlen;
+ GstBuffer *buf;
+
+ while ((bs->index + len) > bs->size) {
+ buf = gst_pad_pull (bs->pad);
+ oldlen = bs->size - bs->index;
+ memmove (bs->data, bs->data + bs->index, oldlen);
+ bs->size = oldlen + GST_BUFFER_SIZE (buf);
+ bs->index = 0;
+ bs->data = realloc (bs->data, bs->size);
+ if (!bs->data) {
+ fprintf (stderr, "realloc failed: d:%p s:%d\n", bs->data, bs->size);
+ }
+ memcpy (bs->data + oldlen, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ }
+ g_assert ((bs->index + len) <= bs->size);
+}
+
+guint8 *
+gst_bytestream_bytes_peek (GstByteStream * bs, guint64 len)
+{
+ g_return_val_if_fail (len > 0, NULL);
+
+ gst_bytestream_bytes_fill (bs, len);
+
+ return gst_bytestream_pos (bs);
+}
+
+guint8 *
+gst_bytestream_bytes_read (GstByteStream * bs, guint64 len)
+{
+ guint8 *ptr;
+
+ g_return_val_if_fail (len > 0, NULL);
+
+ gst_bytestream_bytes_fill (bs, len);
+ ptr = gst_bytestream_pos (bs);
+ bs->index += len;
+
+ return ptr;
+}
+
+gboolean
+gst_bytestream_bytes_seek (GstByteStream * bs, guint64 offset)
+{
+ return FALSE;
+}
+
+void
+gst_bytestream_bytes_flush (GstByteStream * bs, guint64 len)
+{
+ gst_bytestream_bytes_read (bs, len);
+}
diff --git a/gst/utils/gstbytestream.h b/gst/utils/gstbytestream.h
new file mode 100644
index 0000000000..f368bb31b4
--- /dev/null
+++ b/gst/utils/gstbytestream.h
@@ -0,0 +1,56 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstbytestream.h: Header for various utility functions
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_BYTESTREAM_H__
+#define __GST_BYTESTREAM_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _GstByteStream GstByteStream;
+
+struct _GstByteStream
+{
+ GstPad *pad;
+ guint8 *data;
+ guint64 size;
+ guint64 index;
+};
+
+GstByteStream* gst_bytestream_new (GstPad *pad);
+void gst_bytestream_destroy (GstByteStream *bs);
+
+gint gst_bytestream_bytes_peek (GstByteStream *bs, guint8 **buf, guint64 len);
+gint gst_bytestream_bytes_read (GstByteStream *bs, guint8 **buf, guint64 len);
+gboolean gst_bytestream_bytes_seek (GstByteStream *bs, guint64 offset);
+gint gst_bytestream_bytes_flush (GstByteStream *bs, guint64 len);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __GST_BYTESTREAM_H__ */
diff --git a/gstplay/gstplay.c b/gstplay/gstplay.c
index 4c4073266b..42071c33f6 100644
--- a/gstplay/gstplay.c
+++ b/gstplay/gstplay.c
@@ -402,7 +402,7 @@ gst_play_set_uri (GstPlay *play, const guchar *uri)
}
if (priv->src == NULL) {
- priv->src = gst_elementfactory_make ("disksrc", "srcelement");
+ priv->src = gst_elementfactory_make ("filesrc", "srcelement");
}
priv->uri = g_strdup (uri);
diff --git a/gstplay/main.c b/gstplay/main.c
index 0d968dce21..f8a6859b0f 100644
--- a/gstplay/main.c
+++ b/gstplay/main.c
@@ -25,7 +25,9 @@ main (int argc, char *argv[])
}
}
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile ("gstmediaplay.gst", gst_xml_write (gst_play_get_pipeline (play->play)));
+#endif
gdk_threads_enter();
gst_main();
diff --git a/libs/Makefile.am b/libs/Makefile.am
index 23bcb8ad45..581277f9d2 100644
--- a/libs/Makefile.am
+++ b/libs/Makefile.am
@@ -1,4 +1,3 @@
+SUBDIRS = riff getbits putbits idct audio bytestream control
-SUBDIRS = riff getbits putbits idct audio control
-
-DIST_SUBDIRS = riff getbits putbits audio idct control
+DIST_SUBDIRS = riff getbits putbits audio idct bytestream control
diff --git a/libs/bytestream/Makefile.am b/libs/bytestream/Makefile.am
new file mode 100644
index 0000000000..0a6e8ee9cf
--- /dev/null
+++ b/libs/bytestream/Makefile.am
@@ -0,0 +1,11 @@
+filterdir = $(libdir)/gst
+
+filter_LTLIBRARIES = libgstbytestream.la libgstbstest.la
+
+libgstbytestream_la_SOURCES = gstbytestream.c
+libgstbstest_la_SOURCES = gstbstest.c
+
+libgstbytestreamincludedir = $(includedir)/gst/libs/bytestream
+libgstbytestreaminclude_HEADERS = gstbytestream.h
+
+# CFLAGS += -O2 $(FOMIT_FRAME_POINTER) -funroll-all-loops -finline-functions -ffast-math
diff --git a/libs/bytestream/gstbstest.c b/libs/bytestream/gstbstest.c
new file mode 100644
index 0000000000..087d63ade7
--- /dev/null
+++ b/libs/bytestream/gstbstest.c
@@ -0,0 +1,294 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstidentity.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include
+#include "gstbytestream.h"
+
+#define GST_TYPE_IDENTITY \
+ (gst_identity_get_type())
+#define GST_IDENTITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IDENTITY,GstIdentity))
+#define GST_IDENTITY_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IDENTITY,GstIdentityClass))
+#define GST_IS_IDENTITY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IDENTITY))
+#define GST_IS_IDENTITY_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IDENTITY))
+
+typedef struct _GstIdentity GstIdentity;
+typedef struct _GstIdentityClass GstIdentityClass;
+
+struct _GstIdentity {
+ GstElement element;
+
+ GstPad *sinkpad;
+ GstPad *srcpad;
+
+ GstByteStream *bs;
+ gint byte_size;
+ gint count;
+};
+
+struct _GstIdentityClass {
+ GstElementClass parent_class;
+};
+
+GType gst_identity_get_type(void);
+
+
+GstElementDetails gst_identity_details = {
+ "ByteStreamTest",
+ "Filter",
+ "Test for the GstByteStream code",
+ VERSION,
+ "Erik Walthinsen ",
+ "(C) 2001",
+};
+
+
+/* Identity signals and args */
+enum {
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum {
+ ARG_0,
+ ARG_BYTE_SIZE,
+ ARG_COUNT,
+};
+
+
+static void gst_identity_class_init (GstIdentityClass *klass);
+static void gst_identity_init (GstIdentity *identity);
+
+static void gst_identity_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
+static void gst_identity_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+
+static void gst_identity_loop (GstElement *element);
+
+static GstElementClass *parent_class = NULL;
+// static guint gst_identity_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_identity_get_type (void)
+{
+ static GType identity_type = 0;
+
+ if (!identity_type) {
+ static const GTypeInfo identity_info = {
+ sizeof(GstIdentityClass), NULL,
+ NULL,
+ (GClassInitFunc)gst_identity_class_init,
+ NULL,
+ NULL,
+ sizeof(GstIdentity),
+ 0,
+ (GInstanceInitFunc)gst_identity_init,
+ };
+ identity_type = g_type_register_static (GST_TYPE_ELEMENT, "GstBSTest", &identity_info, 0);
+ }
+ return identity_type;
+}
+
+static void
+gst_identity_class_init (GstIdentityClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass*)klass;
+
+ parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BYTE_SIZE,
+ g_param_spec_uint ("byte_size", "byte_size", "byte_size",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COUNT,
+ g_param_spec_uint ("count", "count", "count",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE));
+
+ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_identity_set_property);
+ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_identity_get_property);
+}
+
+static GstPadNegotiateReturn
+gst_identity_negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+ GstIdentity *identity;
+
+ identity = GST_IDENTITY (gst_pad_get_parent (pad));
+
+ return gst_pad_negotiate_proxy (pad, identity->sinkpad, caps);
+}
+
+static GstPadNegotiateReturn
+gst_identity_negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+ GstIdentity *identity;
+
+ identity = GST_IDENTITY (gst_pad_get_parent (pad));
+
+ return gst_pad_negotiate_proxy (pad, identity->srcpad, caps);
+}
+
+static void
+gst_identity_init (GstIdentity *identity)
+{
+ identity->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+ gst_element_add_pad (GST_ELEMENT (identity), identity->sinkpad);
+ gst_pad_set_negotiate_function (identity->sinkpad, gst_identity_negotiate_sink);
+
+ identity->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+ gst_element_add_pad (GST_ELEMENT (identity), identity->srcpad);
+ gst_pad_set_negotiate_function (identity->srcpad, gst_identity_negotiate_src);
+
+ gst_element_set_loop_function (GST_ELEMENT (identity), gst_identity_loop);
+
+ identity->byte_size = 384;
+ identity->count = 5;
+
+ identity->bs = gst_bytestream_new(identity->sinkpad);
+}
+
+static void
+gst_identity_loop (GstElement *element)
+{
+ GstIdentity *identity;
+ GstBuffer *buf;
+ int i;
+
+ g_return_if_fail (element != NULL);
+ g_return_if_fail (GST_IS_IDENTITY (element));
+
+ identity = GST_IDENTITY (element);
+
+/* THIS IS THE BUFFER BASED ONE
+ do {
+// g_print("\n");
+
+ for (i=0;icount;i++) {
+// g_print("bstest: getting a buffer of %d bytes\n",identity->byte_size);
+ buf = gst_bytestream_read(identity->bs,identity->byte_size);
+ if (!buf) g_print("BUFFER IS BOGUS\n");
+// g_print("pushing the buffer, %d bytes at %d\n",GST_BUFFER_SIZE(buf),GST_BUFFER_OFFSET(buf));
+ gst_pad_push(identity->srcpad,buf);
+// g_print("\n");
+ gst_bytestream_print_status(identity->bs);
+// g_print("\n\n");
+ }
+
+ exit(1);
+ } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element));
+*/
+
+/* THIS IS THE BYTE BASED ONE*/
+ do {
+ for (i=0;icount;i++) {
+ buf = gst_buffer_new();
+ // note that this is dangerous, as it does *NOT* refcount the data, it can go away!!!
+ GST_BUFFER_DATA(buf) = gst_bytestream_peek_bytes(identity->bs,identity->byte_size);
+ GST_BUFFER_SIZE(buf) = identity->byte_size;
+ GST_BUFFER_FLAG_SET(buf,GST_BUFFER_DONTFREE);
+ gst_pad_push(identity->srcpad,buf);
+ gst_bytestream_flush(identity->bs,identity->byte_size);
+ }
+
+ exit(1);
+ } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element));
+/**/
+}
+
+static void
+gst_identity_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GstIdentity *identity;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (GST_IS_IDENTITY (object));
+
+ identity = GST_IDENTITY (object);
+
+ switch (prop_id) {
+ case ARG_BYTE_SIZE:
+ identity->byte_size = g_value_get_uint (value);
+ break;
+ case ARG_COUNT:
+ identity->count = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void gst_identity_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
+ GstIdentity *identity;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (GST_IS_IDENTITY (object));
+
+ identity = GST_IDENTITY (object);
+
+ switch (prop_id) {
+ case ARG_BYTE_SIZE:
+ g_value_set_uint (value, identity->byte_size);
+ break;
+ case ARG_COUNT:
+ g_value_set_uint (value, identity->count);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static gboolean
+plugin_init (GModule *module, GstPlugin *plugin)
+{
+ GstElementFactory *factory;
+
+ // we need gstbytestream
+ if (!gst_library_load ("gstbytestream")) {
+ g_print("can't load bytestream\n");
+ return FALSE;
+ }
+
+ /* We need to create an ElementFactory for each element we provide.
+ * This consists of the name of the element, the GType identifier,
+ * and a pointer to the details structure at the top of the file.
+ */
+ factory = gst_elementfactory_new("gstbstest", GST_TYPE_IDENTITY, &gst_identity_details);
+ g_return_val_if_fail(factory != NULL, FALSE);
+
+ /* The very last thing is to register the elementfactory with the plugin. */
+ gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+ return TRUE;
+}
+
+GstPluginDesc plugin_desc = {
+ GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "gstbstest",
+ plugin_init
+};
+
diff --git a/libs/bytestream/gstbytestream.c b/libs/bytestream/gstbytestream.c
new file mode 100644
index 0000000000..6f4d18a3f1
--- /dev/null
+++ b/libs/bytestream/gstbytestream.c
@@ -0,0 +1,394 @@
+/* GStreamer
+ * Copyright (C) 2001 Erik Walthinsen
+ *
+ * gstbytestream.c: adds a convenient bytestream based API to a pad.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include
+#include
+#include
+
+#include
+#include "gstbytestream.h"
+
+//#define BS_DEBUG
+
+#ifdef BS_DEBUG
+# define bs_print(format,args...) GST_DEBUG (GST_CAT_BUFFER, format, ## args)
+# define bs_status(bs) gst_bytestream_print_status(bs)
+#else
+# define bs_print(format,args...)
+# define bs_status(bs)
+#endif
+
+guint8 *gst_bytestream_assemble (GstByteStream * bs, guint32 len);
+
+/**
+ * gst_bytestream_new:
+ * @pad: the pad to attach the bytestream to
+ *
+ * creates a bytestream from the given pad
+ *
+ * Returns: a new #GstByteStream object
+ */
+GstByteStream *
+gst_bytestream_new (GstPad * pad)
+{
+ GstByteStream *bs = g_new (GstByteStream, 1);
+
+ bs->pad = pad;
+
+ bs->buflist = NULL;
+ bs->headbufavail = 0;
+ bs->listavail = 0;
+ bs->assembled = NULL;
+
+ return bs;
+}
+
+void
+gst_bytestream_destroy (GstByteStream * bs)
+{
+ GSList *walk;
+
+ walk = bs->buflist;
+ while (walk) {
+ gst_buffer_unref (GST_BUFFER (walk->data));
+ walk = g_slist_next (walk);
+ }
+ g_slist_free (bs->buflist);
+ if (bs->assembled)
+ g_free (bs->assembled);
+ g_free (bs);
+}
+
+// HOW THIS WORKS:
+//
+// The fundamental structure is a singly-linked list of buffers. The
+// buffer on the front is the oldest, and thus the first to read data
+// from. The number of bytes left to be read in this buffer is stored
+// in bs->headbufavail. The number of bytes available in the entire
+// list (including the head buffer) is in bs->listavail.
+//
+// When a request is made for data (peek), _fill_bytes is called with
+// the number of bytes needed, but only if the listavail indicates
+// that there aren't already enough. This calls _get_next_buf until
+// the listavail is sufficient to satisfy the demand.
+//
+// _get_next_buf pulls a buffer from the pad the bytestream is attached
+// to, and shoves it in the list. There are actually two things it can
+// do. If there's already a buffer in the list, and the _is_span_fast()
+// test returns true, it will merge it with that last buffer. Otherwise
+// it will simply tack it onto the end of the list.
+//
+// The _peek itself first checks the simple case of the request fitting
+// within the head buffer, and if so creates a subbuffer and returns.
+// Otherwise, it creates a new buffer and allocates space for the request
+// and calls _assemble to fill it. We know we have to copy because this
+// case only happens when the _merge wasn't feasible during _get_next_buf.
+//
+// The _flush method repeatedly inspects the head buffer and flushes as
+// much data from it as it needs to, up to the size of the buffer. If
+// the flush decimates the buffer, it's stripped, unref'd, and removed.
+
+
+// get the next buffer
+// if the buffer can be merged with the head buffer, do so
+// else add it onto the head of the
+static gboolean
+gst_bytestream_get_next_buf (GstByteStream * bs)
+{
+ GstBuffer *nextbuf, *lastbuf;
+ GSList *end;
+
+ bs_print ("get_next_buf: pulling buffer\n");
+ nextbuf = gst_pad_pull (bs->pad);
+ bs_print ("get_next_buf: got buffer of %d bytes\n", GST_BUFFER_SIZE (nextbuf));
+
+ // first see if there are any buffers in the list at all
+ if (bs->buflist) {
+ bs_print ("gst_next_buf: there is at least one buffer in the list\n");
+ // now find the end of the list
+ end = g_slist_last (bs->buflist);
+ // get the buffer that's there
+ lastbuf = GST_BUFFER (end->data);
+
+ // see if we can marge cheaply
+ if (gst_buffer_is_span_fast (lastbuf, nextbuf)) {
+ bs_print ("get_next_buf: merging new buffer with last buf on list\n");
+ // it is, let's merge them (this is really an append, but...)
+ end->data = gst_buffer_merge (lastbuf, nextbuf);
+ // add to the length of the list
+ bs->listavail += GST_BUFFER_SIZE (nextbuf);
+
+ // have to check to see if we merged with the head buffer
+ if (end == bs->buflist) {
+ bs->headbufavail += GST_BUFFER_SIZE (nextbuf);
+ }
+
+ gst_buffer_unref (lastbuf);
+ gst_buffer_unref (nextbuf);
+
+ // if we can't, we just append this buffer
+ }
+ else {
+ bs_print ("get_next_buf: adding new buffer to the end of the list\n");
+ end = g_slist_append (end, nextbuf);
+ // also need to increment length of list and buffer count
+ bs->listavail += GST_BUFFER_SIZE (nextbuf);
+ }
+
+ // if there are no buffers in the list
+ }
+ else {
+ bs_print ("get_next_buf: buflist is empty, adding new buffer to list\n");
+ // put this on the end of the list
+ bs->buflist = g_slist_append (bs->buflist, nextbuf);
+ // and increment the number of bytes in the list
+ bs->listavail = GST_BUFFER_SIZE (nextbuf);
+ // set the head buffer avail to the size
+ bs->headbufavail = GST_BUFFER_SIZE (nextbuf);
+ }
+
+ return TRUE;
+}
+
+
+static gboolean
+gst_bytestream_fill_bytes (GstByteStream * bs, guint32 len)
+{
+ // as long as we don't have enough, we get more buffers
+ while (bs->listavail < len) {
+ bs_print ("fill_bytes: there are %d bytes in the list, we need %d\n", bs->listavail, len);
+ gst_bytestream_get_next_buf (bs);
+ }
+
+ return TRUE;
+}
+
+
+GstBuffer *
+gst_bytestream_peek (GstByteStream * bs, guint32 len)
+{
+ GstBuffer *headbuf, *retbuf = NULL;
+
+ g_return_val_if_fail (bs != NULL, NULL);
+ g_return_val_if_fail (len > 0, NULL);
+
+ bs_print ("peek: asking for %d bytes\n", len);
+
+ // make sure we have enough
+ bs_print ("peek: there are %d bytes in the list\n", bs->listavail);
+ if (len > bs->listavail) {
+ gst_bytestream_fill_bytes (bs, len);
+ bs_print ("peek: there are now %d bytes in the list\n", bs->listavail);
+ }
+ bs_status (bs);
+
+ // extract the head buffer
+ headbuf = GST_BUFFER (bs->buflist->data);
+
+ // if the requested bytes are in the current buffer
+ bs_print ("peek: headbufavail is %d\n", bs->headbufavail);
+ if (len <= bs->headbufavail) {
+ bs_print ("peek: there are enough bytes in headbuf (need %d, have %d)\n", len, bs->headbufavail);
+ // create a sub-buffer of the headbuf
+ retbuf = gst_buffer_create_sub (headbuf, GST_BUFFER_SIZE (headbuf) - bs->headbufavail, len);
+
+ // otherwise we need to figure out how to assemble one
+ }
+ else {
+ bs_print ("peek: current buffer is not big enough for len %d\n", len);
+
+ retbuf = gst_buffer_new ();
+ GST_BUFFER_SIZE (retbuf) = len;
+ GST_BUFFER_DATA (retbuf) = gst_bytestream_assemble (bs, len);
+ if (GST_BUFFER_OFFSET (headbuf) != -1)
+ GST_BUFFER_OFFSET (retbuf) = GST_BUFFER_OFFSET (headbuf) + (GST_BUFFER_SIZE (headbuf) - bs->headbufavail);
+ }
+
+ return retbuf;
+}
+
+guint8 *
+gst_bytestream_peek_bytes (GstByteStream * bs, guint32 len)
+{
+ GstBuffer *headbuf;
+ guint8 *data = NULL;
+
+ g_return_val_if_fail (bs != NULL, NULL);
+ g_return_val_if_fail (len > 0, NULL);
+
+ bs_print ("peek_bytes: asking for %d bytes\n", len);
+ if (bs->assembled) {
+ g_free (bs->assembled);
+ bs->assembled = NULL;
+ }
+
+ // make sure we have enough
+ bs_print ("peek_bytes: there are %d bytes in the list\n", bs->listavail);
+ if (len > bs->listavail) {
+ gst_bytestream_fill_bytes (bs, len);
+ bs_print ("peek_bytes: there are now %d bytes in the list\n", bs->listavail);
+ }
+ bs_status (bs);
+
+ // extract the head buffer
+ headbuf = GST_BUFFER (bs->buflist->data);
+
+ // if the requested bytes are in the current buffer
+ bs_print ("peek_bytes: headbufavail is %d\n", bs->headbufavail);
+ if (len <= bs->headbufavail) {
+ bs_print ("peek_bytes: there are enough bytes in headbuf (need %d, have %d)\n", len, bs->headbufavail);
+ // create a sub-buffer of the headbuf
+ data = GST_BUFFER_DATA (headbuf) + (GST_BUFFER_SIZE (headbuf) - bs->headbufavail);
+
+ // otherwise we need to figure out how to assemble one
+ }
+ else {
+ bs_print ("peek_bytes: current buffer is not big enough for len %d\n", len);
+
+ data = gst_bytestream_assemble (bs, len);
+ bs->assembled = data;
+ bs->assembled_len = len;
+ }
+
+ return data;
+}
+
+guint8 *
+gst_bytestream_assemble (GstByteStream * bs, guint32 len)
+{
+ guint8 *data = g_malloc (len);
+ GSList *walk;
+ guint32 copied = 0;
+ GstBuffer *buf;
+
+ // copy the data from the curbuf
+ buf = GST_BUFFER (bs->buflist->data);
+ bs_print ("assemble: copying %d bytes from curbuf at %d to *data\n", bs->headbufavail,
+ GST_BUFFER_SIZE (buf) - bs->headbufavail);
+ memcpy (data, GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf) - bs->headbufavail, bs->headbufavail);
+ copied += bs->headbufavail;
+
+ // asumption is made that the buffers all exist in the list
+ walk = g_slist_next (bs->buflist);
+ while (copied < len) {
+ buf = GST_BUFFER (walk->data);
+ if (GST_BUFFER_SIZE (buf) < (len - copied)) {
+ bs_print ("assemble: copying %d bytes from buf to output offset %d\n", GST_BUFFER_SIZE (buf), copied);
+ memcpy (data + copied, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ copied += GST_BUFFER_SIZE (buf);
+ }
+ else {
+ bs_print ("assemble: copying %d bytes from buf to output offset %d\n", len - copied, copied);
+ memcpy (data + copied, GST_BUFFER_DATA (buf), len - copied);
+ copied = len;
+ }
+ walk = g_slist_next (walk);
+ }
+
+ return data;
+}
+
+gboolean
+gst_bytestream_flush (GstByteStream * bs, guint32 len)
+{
+ GstBuffer *headbuf;
+
+ bs_print ("flush: flushing %d bytes\n", len);
+ if (bs->assembled) {
+ g_free (bs->assembled);
+ bs->assembled = NULL;
+ }
+
+ // make sure we have enough
+ bs_print ("flush: there are %d bytes in the list\n", bs->listavail);
+ if (len > bs->listavail) {
+ gst_bytestream_fill_bytes (bs, len);
+ bs_print ("flush: there are now %d bytes in the list\n", bs->listavail);
+ }
+
+ // repeat until we've flushed enough data
+ while (len > 0) {
+ headbuf = GST_BUFFER (bs->buflist->data);
+
+ bs_print ("flush: analyzing buffer that's %d bytes long, offset %d\n", GST_BUFFER_SIZE (headbuf),
+ GST_BUFFER_OFFSET (headbuf));
+
+ // if there's enough to complete the flush
+ if (bs->headbufavail > len) {
+ // just trim it off
+ bs_print ("flush: trimming %d bytes off end of headbuf\n", len);
+ bs->headbufavail -= len;
+ bs->listavail -= len;
+ len = 0;
+
+ // otherwise we have to trim the whole buffer
+ }
+ else {
+ bs_print ("flush: removing head buffer completely\n");
+ // remove it from the list
+ bs->buflist = g_slist_delete_link (bs->buflist, bs->buflist);
+ // trim it from the avail size
+ bs->listavail -= bs->headbufavail;
+ // record that we've trimmed this many bytes
+ len -= bs->headbufavail;
+ // unref it
+ gst_buffer_unref (headbuf);
+
+ // record the new headbufavail
+ if (bs->buflist) {
+ bs->headbufavail = GST_BUFFER_SIZE (GST_BUFFER (bs->buflist->data));
+ bs_print ("flush: next headbuf is %d bytes\n", bs->headbufavail);
+ }
+ else {
+ bs_print ("flush: no more bytes at all\n");
+ }
+ }
+
+ bs_print ("flush: bottom of while(), len is now %d\n", len);
+ }
+
+ return TRUE;
+}
+
+GstBuffer *
+gst_bytestream_read (GstByteStream * bs, guint32 len)
+{
+ GstBuffer *buf = gst_bytestream_peek (bs, len);
+ gst_bytestream_flush (bs, len);
+ return buf;
+}
+
+void
+gst_bytestream_print_status (GstByteStream * bs)
+{
+ GSList *walk;
+ GstBuffer *buf;
+
+ bs_print ("STATUS: head buffer has %d bytes available\n", bs->headbufavail);
+ bs_print ("STATUS: list has %d bytes available\n", bs->listavail);
+ walk = bs->buflist;
+ while (walk) {
+ buf = GST_BUFFER (walk->data);
+ walk = g_slist_next (walk);
+
+ bs_print ("STATUS: buffer starts at %d and is %d bytes long\n", GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf));
+ }
+}
diff --git a/libs/bytestream/gstbytestream.h b/libs/bytestream/gstbytestream.h
new file mode 100644
index 0000000000..fd01a973ee
--- /dev/null
+++ b/libs/bytestream/gstbytestream.h
@@ -0,0 +1,53 @@
+/* GStreamer
+ * Copyright (C) 2001 Erik Walthinsen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_BYTESTREAM_H__
+#define __GST_BYTESTREAM_H__
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _GstByteStream GstByteStream;
+
+struct _GstByteStream {
+ GstPad *pad;
+
+ GSList *buflist;
+ guint32 headbufavail;
+ guint32 listavail;
+
+ // we keep state of assembled pieces
+ guint8 *assembled;
+ guint32 assembled_len;
+};
+
+GstByteStream* gst_bytestream_new (GstPad *pad);
+void gst_bytestream_destroy (GstByteStream *bs);
+
+GstBuffer* gst_bytestream_read (GstByteStream *bs, guint32 len);
+GstBuffer* gst_bytestream_peek (GstByteStream *bs, guint32 len);
+guint8* gst_bytestream_peek_bytes (GstByteStream *bs, guint32 len);
+gboolean gst_bytestream_flush (GstByteStream *bs, guint32 len);
+
+void gst_bytestream_print_status (GstByteStream *bs);
+
+#endif /* __GST_BYTESTREAM_H__ */
diff --git a/plugins/elements/Makefile.am b/plugins/elements/Makefile.am
index 61c5ad7c16..f50e4f75b4 100644
--- a/plugins/elements/Makefile.am
+++ b/plugins/elements/Makefile.am
@@ -8,6 +8,8 @@ else
GSTHTTPSRC=
endif
+#CFLAGS += -O2 -Wall -finstrument-functions -DGST_ENABLE_FUNC_INSTRUMENTATION
+
libgstelements_la_DEPENDENCIES = ../libgst.la
libgstelements_la_SOURCES = \
gstelements.c \
@@ -37,8 +39,10 @@ noinst_HEADERS = \
gstfdsink.h \
gstpipefilter.h \
gsttee.h \
- gstaggregator.h
-CFLAGS += -O2 -Wall
+ gstaggregator.h \
+ gstsinesrc.h
+
+CFLAGS += -O2 -Wall
LDFLAGS += -lm
libgstelements_la_LIBADD = $(GHTTP_LIBS)
diff --git a/plugins/elements/gstaggregator.c b/plugins/elements/gstaggregator.c
index eb6c3013d9..49ec28f167 100644
--- a/plugins/elements/gstaggregator.c
+++ b/plugins/elements/gstaggregator.c
@@ -76,7 +76,8 @@ gst_aggregator_sched_get_type (void)
static void gst_aggregator_class_init (GstAggregatorClass *klass);
static void gst_aggregator_init (GstAggregator *aggregator);
-static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp);
+static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp, const
+ gchar *unused);
static void gst_aggregator_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
@@ -150,7 +151,7 @@ gst_aggregator_init (GstAggregator *aggregator)
}
static GstPad*
-gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ)
+gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
{
gchar *name;
GstPad *sinkpad;
diff --git a/plugins/elements/gstdisksrc.c b/plugins/elements/gstdisksrc.c
index ab13968eb9..ffe1b352e1 100644
--- a/plugins/elements/gstdisksrc.c
+++ b/plugins/elements/gstdisksrc.c
@@ -64,8 +64,8 @@ static void gst_disksrc_set_property (GObject *object, guint prop_id,
static void gst_disksrc_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
-static GstBuffer * gst_disksrc_get (GstPad *pad);
-static GstBuffer * gst_disksrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len);
+static GstBuffer* gst_disksrc_get (GstPad *pad);
+static GstBufferPool* gst_disksrc_get_bufferpool (GstPad *pad);
static GstElementStateReturn
gst_disksrc_change_state (GstElement *element);
@@ -73,7 +73,7 @@ static GstElementStateReturn
static gboolean gst_disksrc_open_file (GstDiskSrc *src);
static void gst_disksrc_close_file (GstDiskSrc *src);
-static GstElementClass *parent_class = NULL;
+static GstElementClass* parent_class = NULL;
//static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 };
GType
@@ -133,8 +133,8 @@ gst_disksrc_init (GstDiskSrc *disksrc)
// GST_FLAG_SET (disksrc, GST_SRC_);
disksrc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
- gst_pad_set_get_function (disksrc->srcpad,gst_disksrc_get);
- gst_pad_set_getregion_function (disksrc->srcpad,gst_disksrc_get_region);
+ gst_pad_set_get_function (disksrc->srcpad, gst_disksrc_get);
+ gst_pad_set_bufferpool_function (disksrc->srcpad, gst_disksrc_get_bufferpool);
gst_element_add_pad (GST_ELEMENT (disksrc), disksrc->srcpad);
disksrc->filename = NULL;
@@ -220,6 +220,56 @@ gst_disksrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
}
}
+static GstBuffer*
+gst_disksrc_buffer_new (GstBufferPool *pool, gint64 location, gint size, gpointer user_data)
+{
+ GstDiskSrc *src;
+ GstBuffer *buf;
+
+ src = GST_DISKSRC (user_data);
+
+ buf = gst_buffer_new ();
+ g_return_val_if_fail (buf != NULL, NULL);
+
+ /* simply set the buffer to point to the correct region of the file */
+ GST_BUFFER_DATA (buf) = src->map + location;
+ GST_BUFFER_OFFSET (buf) = location;
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
+
+ if ((location + size) > src->size)
+ GST_BUFFER_SIZE (buf) = src->size - location;
+ else
+ GST_BUFFER_SIZE (buf) = size;
+
+ GST_DEBUG (0,"map %p, offset %ld (%p), size %d\n", src->map, src->curoffset,
+ src->map + src->curoffset, GST_BUFFER_SIZE (buf));
+
+ return buf;
+}
+
+static void
+gst_disksrc_buffer_free (GstBuffer *buf)
+{
+ // FIXME do something here
+}
+
+static GstBufferPool*
+gst_disksrc_get_bufferpool (GstPad *pad)
+{
+ GstDiskSrc *src;
+
+ src = GST_DISKSRC (gst_pad_get_parent (pad));
+
+ if (!src->bufferpool) {
+ src->bufferpool = gst_buffer_pool_new ();
+ gst_buffer_pool_set_buffer_new_function (src->bufferpool, gst_disksrc_buffer_new);
+ gst_buffer_pool_set_buffer_free_function (src->bufferpool, gst_disksrc_buffer_free);
+ gst_buffer_pool_set_user_data (src->bufferpool, src);
+ }
+
+ return src->bufferpool;
+}
+
/**
* gst_disksrc_get:
* @pad: #GstPad to push a buffer from
@@ -246,28 +296,10 @@ gst_disksrc_get (GstPad *pad)
return buf;
}
- /* create the buffer */
- // FIXME: should eventually use a bufferpool for this
- buf = gst_buffer_new ();
-
- g_return_val_if_fail (buf != NULL, NULL);
-
- /* simply set the buffer to point to the correct region of the file */
- GST_BUFFER_DATA (buf) = src->map + src->curoffset;
- GST_BUFFER_OFFSET (buf) = src->curoffset;
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
-
- if ((src->curoffset + src->bytes_per_read) > src->size) {
- GST_BUFFER_SIZE (buf) = src->size - src->curoffset;
- // FIXME: set the buffer's EOF bit here
- } else
- GST_BUFFER_SIZE (buf) = src->bytes_per_read;
-
- GST_DEBUG (0,"map %p, offset %ld (%p), size %d\n", src->map, src->curoffset,
- src->map + src->curoffset, GST_BUFFER_SIZE (buf));
+ // FIXME use a bufferpool
+ buf = gst_disksrc_buffer_new (NULL, src->curoffset, src->bytes_per_read, src);
//gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
-
src->curoffset += GST_BUFFER_SIZE (buf);
if (src->new_seek) {
@@ -280,61 +312,6 @@ gst_disksrc_get (GstPad *pad)
return buf;
}
-/**
- * gst_disksrc_get_region:
- * @src: #GstSrc to push a buffer from
- * @offset: offset in file
- * @size: number of bytes
- *
- * Push a new buffer from the disksrc of given size at given offset.
- */
-static GstBuffer *
-gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
-{
- GstDiskSrc *src;
- GstBuffer *buf;
-
- g_return_val_if_fail (pad != NULL, NULL);
- g_return_val_if_fail (type == GST_REGION_OFFSET_LEN, NULL);
-
- src = GST_DISKSRC (gst_pad_get_parent (pad));
-
- g_return_val_if_fail (GST_IS_DISKSRC (src), NULL);
- g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL);
-
- /* deal with EOF state */
- if (offset >= src->size) {
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- GST_DEBUG (0,"map offset %lld >= size %ld --> eos\n", offset, src->size);
- //FIXME
- buf = gst_buffer_new();
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_EOS);
- return buf;
- }
-
- /* create the buffer */
- // FIXME: should eventually use a bufferpool for this
- buf = gst_buffer_new ();
- g_return_val_if_fail (buf != NULL, NULL);
-
- /* simply set the buffer to point to the correct region of the file */
- GST_BUFFER_DATA (buf) = src->map + offset;
- GST_BUFFER_OFFSET (buf) = offset;
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
-
- if ((offset + len) > src->size) {
- GST_BUFFER_SIZE (buf) = src->size - offset;
- // FIXME: set the buffer's EOF bit here
- } else
- GST_BUFFER_SIZE (buf) = len;
-
- GST_DEBUG (0,"map %p, offset %lld, size %d\n", src->map, offset, GST_BUFFER_SIZE (buf));
-
- /* we're done, return the buffer off now */
- return buf;
-}
-
-
/* open the file and mmap it, necessary to go to READY state */
static gboolean
gst_disksrc_open_file (GstDiskSrc *src)
diff --git a/plugins/elements/gstdisksrc.h b/plugins/elements/gstdisksrc.h
index 155a362c2d..4591254734 100644
--- a/plugins/elements/gstdisksrc.h
+++ b/plugins/elements/gstdisksrc.h
@@ -64,6 +64,7 @@ struct _GstDiskSrc {
gchar *filename;
/* fd */
gint fd;
+ GstBufferPool *bufferpool;
/* mapping parameters */
gulong size; /* how long is the file? */
diff --git a/plugins/elements/gstfakesink.c b/plugins/elements/gstfakesink.c
index 11eac007d1..02eb921fa3 100644
--- a/plugins/elements/gstfakesink.c
+++ b/plugins/elements/gstfakesink.c
@@ -45,6 +45,7 @@ enum {
ARG_0,
ARG_NUM_SINKS,
ARG_SILENT,
+ ARG_DUMP,
};
GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
@@ -58,7 +59,8 @@ GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
static void gst_fakesink_class_init (GstFakeSinkClass *klass);
static void gst_fakesink_init (GstFakeSink *fakesink);
-static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ);
+static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const
+ gchar *unused);
static void gst_fakesink_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
@@ -66,7 +68,6 @@ static void gst_fakesink_get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static void gst_fakesink_chain (GstPad *pad, GstBuffer *buf);
-static gboolean gst_fakesink_event (GstPad *pad, GstEventType event, guint64 timestamp, guint32 data);
static GstElementClass *parent_class = NULL;
static guint gst_fakesink_signals[LAST_SIGNAL] = { 0 };
@@ -109,6 +110,9 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
g_param_spec_boolean ("silent", "silent", "silent",
FALSE, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
+ g_param_spec_boolean ("dump", "dump", "dump",
+ FALSE, G_PARAM_READWRITE));
gst_fakesink_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
@@ -129,15 +133,15 @@ gst_fakesink_init (GstFakeSink *fakesink)
pad = gst_pad_new ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (fakesink), pad);
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
- gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_event));
fakesink->sinkpads = g_slist_prepend (NULL, pad);
fakesink->numsinkpads = 1;
fakesink->silent = FALSE;
+ fakesink->dump = FALSE;
}
static GstPad*
-gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ)
+gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
{
gchar *name;
GstPad *sinkpad;
@@ -175,6 +179,9 @@ gst_fakesink_set_property (GObject *object, guint prop_id, const GValue *value,
case ARG_SILENT:
sink->silent = g_value_get_boolean (value);
break;
+ case ARG_DUMP:
+ sink->dump = g_value_get_boolean (value);
+ break;
default:
break;
}
@@ -197,6 +204,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
case ARG_SILENT:
g_value_set_boolean (value, sink->silent);
break;
+ case ARG_DUMP:
+ g_value_set_boolean (value, sink->dump);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -206,9 +216,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
/**
* gst_fakesink_chain:
* @pad: the pad this faksink is connected to
- * @buf: the buffer that has to be absorbed
+ * @buffer: the buffer or event that has to be absorbed
*
- * take the buffer from the pad and unref it without doing
+ * Take the buffer or event from the pad and unref it without doing
* anything with it.
*/
static void
@@ -221,12 +231,33 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
g_return_if_fail (buf != NULL);
fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
+
+ if (GST_IS_EVENT(buf)) {
+ GstEvent *event = GST_EVENT (buf);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ g_print("fakesink: have EOS event!\n");
+ gst_element_set_state (GST_ELEMENT (fakesink), GST_STATE_PAUSED);
+ break;
+ default:
+ g_print("fakesink: have unhandled event!\n");
+ break;
+ }
+ gst_event_free (event);
+ return;
+ }
+
if (!fakesink->silent)
- g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) \n",
- GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
-
- g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0,
- buf);
+ g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) %p\n",
+ GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
+
+ g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
+
+ if (fakesink->dump)
+ {
+ gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ }
gst_buffer_unref (buf);
}
@@ -238,14 +269,3 @@ gst_fakesink_factory_init (GstElementFactory *factory)
return TRUE;
}
-
-
-
-static gboolean
-gst_fakesink_event (GstPad *pad, GstEventType event, guint64 timestamp, guint32 data)
-{
- GST_DEBUG (GST_CAT_EVENT, "fakesink has event %d on pad %s:%s\n",event,GST_DEBUG_PAD_NAME(pad));
- if (event == GST_EVENT_EOS) {
- GST_DEBUG(GST_CAT_EVENT, "have EOS\n");
- }
-}
diff --git a/plugins/elements/gstfakesink.h b/plugins/elements/gstfakesink.h
index cafc18b87c..85aa9fbdb7 100644
--- a/plugins/elements/gstfakesink.h
+++ b/plugins/elements/gstfakesink.h
@@ -57,6 +57,7 @@ struct _GstFakeSink {
GSList *sinkpads;
gint numsinkpads;
gboolean silent;
+ gboolean dump;
};
struct _GstFakeSinkClass {
diff --git a/plugins/elements/gstfakesrc.c b/plugins/elements/gstfakesrc.c
index d946529434..bed56e486f 100644
--- a/plugins/elements/gstfakesrc.c
+++ b/plugins/elements/gstfakesrc.c
@@ -21,6 +21,9 @@
*/
+#include
+#include
+
#include
@@ -47,10 +50,17 @@ enum {
ARG_NUM_SOURCES,
ARG_LOOP_BASED,
ARG_OUTPUT,
+ ARG_DATA,
+ ARG_SIZETYPE,
+ ARG_SIZEMIN,
+ ARG_SIZEMAX,
+ ARG_FILLTYPE,
ARG_PATTERN,
ARG_NUM_BUFFERS,
ARG_EOS,
- ARG_SILENT
+ ARG_SILENT,
+ ARG_DUMP,
+ ARG_PARENTSIZE
};
GST_PADTEMPLATE_FACTORY (fakesrc_src_factory,
@@ -82,12 +92,69 @@ gst_fakesrc_output_get_type (void)
return fakesrc_output_type;
}
+#define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type())
+static GType
+gst_fakesrc_data_get_type (void)
+{
+ static GType fakesrc_data_type = 0;
+ static GEnumValue fakesrc_data[] = {
+ { FAKESRC_DATA_ALLOCATE, "2", "Allocate data"},
+ { FAKESRC_DATA_SUBBUFFER, "3", "Subbuffer data"},
+ {0, NULL, NULL},
+ };
+ if (!fakesrc_data_type) {
+ fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data);
+ }
+ return fakesrc_data_type;
+}
+
+#define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
+static GType
+gst_fakesrc_sizetype_get_type (void)
+{
+ static GType fakesrc_sizetype_type = 0;
+ static GEnumValue fakesrc_sizetype[] = {
+ { FAKESRC_SIZETYPE_NULL, "1", "Send empty buffers"},
+ { FAKESRC_SIZETYPE_FIXED, "2", "Fixed size buffers (sizemax sized)"},
+ { FAKESRC_SIZETYPE_RANDOM, "3", "Random sized buffers (sizemin <= size <= sizemax)"},
+ {0, NULL, NULL},
+ };
+ if (!fakesrc_sizetype_type) {
+ fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
+ }
+ return fakesrc_sizetype_type;
+}
+
+#define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
+static GType
+gst_fakesrc_filltype_get_type (void)
+{
+ static GType fakesrc_filltype_type = 0;
+ static GEnumValue fakesrc_filltype[] = {
+ { FAKESRC_FILLTYPE_NOTHING, "1", "Leave data as malloced"},
+ { FAKESRC_FILLTYPE_NULL, "2", "Fill buffers with zeros"},
+ { FAKESRC_FILLTYPE_RANDOM, "3", "Fill buffers with random crap"},
+ { FAKESRC_FILLTYPE_PATTERN, "4", "Fill buffers with pattern 0x00 -> 0xff"},
+ { FAKESRC_FILLTYPE_PATTERN_CONT, "5", "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
+ {0, NULL, NULL},
+ };
+ if (!fakesrc_filltype_type) {
+ fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
+ }
+ return fakesrc_filltype_type;
+}
+
static void gst_fakesrc_class_init (GstFakeSrcClass *klass);
static void gst_fakesrc_init (GstFakeSrc *fakesrc);
static GstPad* gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ);
-static void gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
-static void gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
+static void gst_fakesrc_update_functions (GstFakeSrc *src);
+static void gst_fakesrc_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void gst_fakesrc_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+
+static GstElementStateReturn gst_fakesrc_change_state (GstElement *element);
static GstBuffer* gst_fakesrc_get (GstPad *pad);
static void gst_fakesrc_loop (GstElement *element);
@@ -137,6 +204,24 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT,
g_param_spec_enum("output","output","output",
GST_TYPE_FAKESRC_OUTPUT,FAKESRC_FIRST_LAST_LOOP,G_PARAM_READWRITE)); // CHECKME!
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
+ g_param_spec_enum ("data", "data", "data",
+ GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
+ g_param_spec_enum ("sizetype", "sizetype", "sizetype",
+ GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
+ g_param_spec_int ("sizemin","sizemin","sizemin",
+ 0, G_MAXINT, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
+ g_param_spec_int ("sizemax","sizemax","sizemax",
+ 0, G_MAXINT, 4096, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
+ g_param_spec_int ("parentsize","parentsize","parentsize",
+ 0, G_MAXINT, 4096 * 10, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
+ g_param_spec_enum ("filltype", "filltype", "filltype",
+ GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE));
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PATTERN,
g_param_spec_string("pattern","pattern","pattern",
NULL, G_PARAM_READWRITE)); // CHECKME
@@ -149,6 +234,9 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SILENT,
g_param_spec_boolean("silent","silent","silent",
FALSE, G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
+ g_param_spec_boolean ("dump","dump","dump",
+ FALSE, G_PARAM_READWRITE));
gst_fakesrc_signals[SIGNAL_HANDOFF] =
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
@@ -159,7 +247,8 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
- gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
+ gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
+ gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
}
static void
@@ -176,17 +265,21 @@ gst_fakesrc_init (GstFakeSrc *fakesrc)
fakesrc->srcpads = g_slist_append (NULL, pad);
fakesrc->loop_based = FALSE;
-
- if (fakesrc->loop_based)
- gst_element_set_loop_function (GST_ELEMENT (fakesrc), GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
- else
- gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
+ gst_fakesrc_update_functions (fakesrc);
fakesrc->num_buffers = -1;
fakesrc->buffer_count = 0;
fakesrc->silent = FALSE;
- // we're ready right away, since we don't have any args...
-// gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_READY);
+ fakesrc->dump = FALSE;
+ fakesrc->pattern_byte = 0x00;
+ fakesrc->need_flush = FALSE;
+ fakesrc->data = FAKESRC_DATA_ALLOCATE;
+ fakesrc->sizetype = FAKESRC_SIZETYPE_NULL;
+ fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING;
+ fakesrc->sizemin = 0;
+ fakesrc->sizemax = 4096;
+ fakesrc->parent = NULL;
+ fakesrc->parentsize = 4096 * 10;
}
static GstPad*
@@ -216,6 +309,34 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
return srcpad;
}
+static gboolean
+gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
+{
+ GstFakeSrc *src;
+
+ src = GST_FAKESRC (gst_pad_get_parent (pad));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_SEEK:
+ g_print("fakesrc: have seek event\n");
+ src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
+ if (!GST_EVENT_SEEK_FLUSH (event)) {
+ gst_event_free (event);
+ break;
+ }
+ // else we do a flush too
+ case GST_EVENT_FLUSH:
+ g_print("fakesrc: have flush event\n");
+ src->need_flush = TRUE;
+ break;
+ default:
+ g_print("fakesrc: have unhandled event\n");
+ break;
+ }
+
+ return TRUE;
+}
+
static void
gst_fakesrc_update_functions (GstFakeSrc *src)
{
@@ -238,10 +359,25 @@ gst_fakesrc_update_functions (GstFakeSrc *src)
else {
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
}
+
+ gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
pads = g_slist_next (pads);
}
}
+static void
+gst_fakesrc_alloc_parent (GstFakeSrc *src)
+{
+ GstBuffer *buf;
+
+ buf = gst_buffer_new ();
+ GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
+ GST_BUFFER_SIZE (buf) = src->parentsize;
+
+ src->parent = buf;
+ src->parentoffset = 0;
+}
+
static void
gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
@@ -257,6 +393,37 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
break;
case ARG_OUTPUT:
break;
+ case ARG_DATA:
+ src->data = g_value_get_int (value);
+ switch (src->data) {
+ case FAKESRC_DATA_ALLOCATE:
+ if (src->parent) {
+ gst_buffer_unref (src->parent);
+ src->parent = NULL;
+ }
+ break;
+ case FAKESRC_DATA_SUBBUFFER:
+ if (!src->parent)
+ gst_fakesrc_alloc_parent (src);
+ default:
+ break;
+ }
+ break;
+ case ARG_SIZETYPE:
+ src->sizetype = g_value_get_int (value);
+ break;
+ case ARG_SIZEMIN:
+ src->sizemin = g_value_get_int (value);
+ break;
+ case ARG_SIZEMAX:
+ src->sizemax = g_value_get_int (value);
+ break;
+ case ARG_PARENTSIZE:
+ src->parentsize = g_value_get_int (value);
+ break;
+ case ARG_FILLTYPE:
+ src->filltype = g_value_get_int (value);
+ break;
case ARG_PATTERN:
break;
case ARG_NUM_BUFFERS:
@@ -269,6 +436,9 @@ GST_INFO (0, "will EOS on next buffer");
case ARG_SILENT:
src->silent = g_value_get_boolean (value);
break;
+ case ARG_DUMP:
+ src->dump = g_value_get_boolean (value);
+ break;
default:
break;
}
@@ -294,6 +464,24 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
case ARG_OUTPUT:
g_value_set_int (value, src->output);
break;
+ case ARG_DATA:
+ g_value_set_int (value, src->data);
+ break;
+ case ARG_SIZETYPE:
+ g_value_set_int (value, src->sizetype);
+ break;
+ case ARG_SIZEMIN:
+ g_value_set_int (value, src->sizemin);
+ break;
+ case ARG_SIZEMAX:
+ g_value_set_int (value, src->sizemax);
+ break;
+ case ARG_PARENTSIZE:
+ g_value_set_int (value, src->parentsize);
+ break;
+ case ARG_FILLTYPE:
+ g_value_set_int (value, src->filltype);
+ break;
case ARG_PATTERN:
g_value_set_string (value, src->pattern);
break;
@@ -306,21 +494,150 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
case ARG_SILENT:
g_value_set_boolean (value, src->silent);
break;
+ case ARG_DUMP:
+ g_value_set_boolean (value, src->dump);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
+static void
+gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
+{
+ if (GST_BUFFER_SIZE (buf) == 0)
+ return;
+
+ switch (src->filltype) {
+ case FAKESRC_FILLTYPE_NULL:
+ memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
+ break;
+ case FAKESRC_FILLTYPE_RANDOM:
+ {
+ gint i;
+ guint8 *ptr = GST_BUFFER_DATA (buf);
+
+ for (i = GST_BUFFER_SIZE (buf); i; i--) {
+ *ptr++ = (gint8)((255.0)*rand()/(RAND_MAX));
+ }
+ break;
+ }
+ case FAKESRC_FILLTYPE_PATTERN:
+ src->pattern_byte = 0x00;
+ case FAKESRC_FILLTYPE_PATTERN_CONT:
+ {
+ gint i;
+ guint8 *ptr = GST_BUFFER_DATA (buf);
+
+ for (i = GST_BUFFER_SIZE (buf); i; i--) {
+ *ptr++ = src->pattern_byte++;
+ }
+ break;
+ }
+ case FAKESRC_FILLTYPE_NOTHING:
+ default:
+ break;
+ }
+}
+
+static GstBuffer*
+gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
+{
+ GstBuffer *buf;
+
+ buf = gst_buffer_new ();
+ GST_BUFFER_SIZE(buf) = size;
+
+ if (size != 0) {
+ switch (src->filltype) {
+ case FAKESRC_FILLTYPE_NOTHING:
+ GST_BUFFER_DATA(buf) = g_malloc (size);
+ break;
+ case FAKESRC_FILLTYPE_NULL:
+ GST_BUFFER_DATA(buf) = g_malloc0 (size);
+ break;
+ case FAKESRC_FILLTYPE_RANDOM:
+ case FAKESRC_FILLTYPE_PATTERN:
+ case FAKESRC_FILLTYPE_PATTERN_CONT:
+ default:
+ GST_BUFFER_DATA(buf) = g_malloc (size);
+ gst_fakesrc_prepare_buffer (src, buf);
+ break;
+ }
+ }
+
+ return buf;
+}
+
+static guint
+gst_fakesrc_get_size (GstFakeSrc *src)
+{
+ guint size;
+
+ switch (src->sizetype) {
+ case FAKESRC_SIZETYPE_FIXED:
+ size = src->sizemax;
+ break;
+ case FAKESRC_SIZETYPE_RANDOM:
+ size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin));
+ break;
+ case FAKESRC_SIZETYPE_NULL:
+ default:
+ size = 0;
+ break;
+ }
+
+ return size;
+}
+
+static GstBuffer *
+gst_fakesrc_create_buffer (GstFakeSrc *src)
+{
+ GstBuffer *buf;
+ guint size;
+ gboolean dump = src->dump;
+
+ size = gst_fakesrc_get_size (src);
+ if (size == 0)
+ return gst_buffer_new();
+
+ switch (src->data) {
+ case FAKESRC_DATA_ALLOCATE:
+ buf = gst_fakesrc_alloc_buffer (src, size);
+ break;
+ case FAKESRC_DATA_SUBBUFFER:
+ // see if we have a parent to subbuffer
+ if (!src->parent) {
+ gst_fakesrc_alloc_parent (src);
+ g_assert (src->parent);
+ }
+ // see if it's large enough
+ if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
+ buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
+ src->parentoffset += size;
+ }
+ else {
+ // the parent is useless now
+ gst_buffer_unref (src->parent);
+ src->parent = NULL;
+ // try again (this will allocate a new parent)
+ return gst_fakesrc_create_buffer (src);
+ }
+ gst_fakesrc_prepare_buffer (src, buf);
+ break;
+ default:
+ g_warning ("fakesrc: dunno how to allocate buffers !");
+ buf = gst_buffer_new();
+ break;
+ }
+ if (dump) {
+ gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ }
+
+ return buf;
+}
-/**
- * gst_fakesrc_get:
- * @src: the faksesrc to get
- *
- * generate an empty buffer and return it
- *
- * Returns: a new empty buffer
- */
static GstBuffer *
gst_fakesrc_get(GstPad *pad)
{
@@ -333,9 +650,16 @@ gst_fakesrc_get(GstPad *pad)
g_return_val_if_fail (GST_IS_FAKESRC (src), NULL);
+ if (src->need_flush) {
+ src->need_flush = FALSE;
+ g_print("fakesrc: sending FLUSH\n");
+ return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
+ }
+
if (src->num_buffers == 0) {
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- return NULL;
+ g_print("fakesrc: sending EOS\n");
+ gst_element_set_state (GST_ELEMENT (src), GST_STATE_PAUSED);
+ return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
}
else {
if (src->num_buffers > 0)
@@ -344,11 +668,11 @@ gst_fakesrc_get(GstPad *pad)
if (src->eos) {
GST_INFO (0, "fakesrc is setting eos on pad");
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- return NULL;
+ g_print("fakesrc: sending EOS\n");
+ return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
}
- buf = gst_buffer_new();
+ buf = gst_fakesrc_create_buffer (src);
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
if (!src->silent)
@@ -356,7 +680,7 @@ gst_fakesrc_get(GstPad *pad)
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
- buf);
+ buf, pad);
return buf;
}
@@ -387,21 +711,20 @@ gst_fakesrc_loop(GstElement *element)
GstBuffer *buf;
if (src->num_buffers == 0) {
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- return;
+ src->eos = TRUE;
}
else {
- if (src->num_buffers > 0)
- src->num_buffers--;
+ if (src->num_buffers > 0)
+ src->num_buffers--;
}
if (src->eos) {
GST_INFO (0, "fakesrc is setting eos on pad");
- gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
- return;
+ gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
+ return;
}
- buf = gst_buffer_new();
+ buf = gst_fakesrc_create_buffer (src);
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
if (!src->silent)
@@ -409,7 +732,7 @@ gst_fakesrc_loop(GstElement *element)
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
- buf);
+ buf, pad);
gst_pad_push (pad, buf);
pads = g_slist_next (pads);
@@ -417,6 +740,31 @@ gst_fakesrc_loop(GstElement *element)
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
}
+static GstElementStateReturn
+gst_fakesrc_change_state (GstElement *element)
+{
+ GstFakeSrc *fakesrc;
+
+ g_return_val_if_fail (GST_IS_FAKESRC (element), GST_STATE_FAILURE);
+
+ fakesrc = GST_FAKESRC (element);
+
+ if (GST_STATE_PENDING (element) == GST_STATE_READY) {
+ fakesrc->buffer_count = 0;
+ fakesrc->pattern_byte = 0x00;
+ fakesrc->need_flush = FALSE;
+ if (fakesrc->parent) {
+ gst_buffer_unref (fakesrc->parent);
+ fakesrc->parent = NULL;
+ }
+ }
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+ return GST_STATE_SUCCESS;
+}
+
gboolean
gst_fakesrc_factory_init (GstElementFactory *factory)
{
diff --git a/plugins/elements/gstfakesrc.h b/plugins/elements/gstfakesrc.h
index ce5c2a9439..550015b2af 100644
--- a/plugins/elements/gstfakesrc.h
+++ b/plugins/elements/gstfakesrc.h
@@ -47,6 +47,25 @@ typedef enum {
FAKESRC_GET_ALWAYS_SUCEEDS,
} GstFakeSrcOutputType;
+typedef enum {
+ FAKESRC_DATA_ALLOCATE = 1,
+ FAKESRC_DATA_SUBBUFFER,
+} GstFakeSrcDataType;
+
+typedef enum {
+ FAKESRC_SIZETYPE_NULL = 1,
+ FAKESRC_SIZETYPE_FIXED,
+ FAKESRC_SIZETYPE_RANDOM
+} GstFakeSrcSizeType;
+
+typedef enum {
+ FAKESRC_FILLTYPE_NOTHING = 1,
+ FAKESRC_FILLTYPE_NULL,
+ FAKESRC_FILLTYPE_RANDOM,
+ FAKESRC_FILLTYPE_PATTERN,
+ FAKESRC_FILLTYPE_PATTERN_CONT
+} GstFakeSrcFillType;
+
#define GST_TYPE_FAKESRC \
(gst_fakesrc_get_type())
#define GST_FAKESRC(obj) \
@@ -64,16 +83,29 @@ typedef struct _GstFakeSrcClass GstFakeSrcClass;
struct _GstFakeSrc {
GstElement element;
- gboolean loop_based;
- gboolean eos;
- gint numsrcpads;
- GSList *srcpads;
+ gboolean loop_based;
+ gboolean eos;
+ gint numsrcpads;
+ GSList *srcpads;
+
GstFakeSrcOutputType output;
- gchar *pattern;
- GList *patternlist;
- gint num_buffers;
- guint64 buffer_count;
- gboolean silent;
+ GstFakeSrcDataType data;
+ GstFakeSrcSizeType sizetype;
+ GstFakeSrcFillType filltype;
+
+ guint sizemin;
+ guint sizemax;
+ GstBuffer *parent;
+ guint parentsize;
+ guint parentoffset;
+ guint8 pattern_byte;
+ gchar *pattern;
+ GList *patternlist;
+ gint num_buffers;
+ guint64 buffer_count;
+ gboolean silent;
+ gboolean dump;
+ gboolean need_flush;
};
struct _GstFakeSrcClass {
diff --git a/plugins/elements/gstfilesrc.c b/plugins/elements/gstfilesrc.c
index 36214941e1..f53548f328 100644
--- a/plugins/elements/gstfilesrc.c
+++ b/plugins/elements/gstfilesrc.c
@@ -27,6 +27,7 @@
#include
#include
#include
+#include
/**********************************************************************
@@ -74,6 +75,9 @@ GstElementDetails gst_filesrc_details = {
"(C) 1999",
};
+//#define fs_print(format,args...) g_print(format, ## args)
+#define fs_print(format,args...)
+
#define GST_TYPE_FILESRC \
(gst_filesrc_get_type())
@@ -110,10 +114,12 @@ struct _GstFileSrc {
gboolean touch; // whether to touch every page
GstBuffer *mapbuf;
- off_t mapsize;
+ size_t mapsize;
GTree *map_regions;
GMutex *map_regions_lock;
+
+ gboolean seek_happened;
};
struct _GstFileSrcClass {
@@ -135,6 +141,7 @@ enum {
ARG_BLOCKSIZE,
ARG_OFFSET,
ARG_MAPSIZE,
+ ARG_TOUCH,
};
@@ -203,6 +210,9 @@ gst_filesrc_class_init (GstFileSrcClass *klass)
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MAPSIZE,
g_param_spec_ulong("mmapsize","mmap() Block Size","Size in bytes of mmap()d regions",
0,G_MAXULONG,4*1048576,G_PARAM_READWRITE));
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TOUCH,
+ g_param_spec_boolean("touch","Touch read data","Touch data to force disk read before push()",
+ TRUE,G_PARAM_READWRITE));
gobject_class->set_property = gst_filesrc_set_property;
gobject_class->get_property = gst_filesrc_get_property;
@@ -246,6 +256,8 @@ gst_filesrc_init (GstFileSrc *src)
src->map_regions = g_tree_new(gst_filesrc_bufcmp);
src->map_regions_lock = g_mutex_new();
+
+ src->seek_happened = FALSE;
}
@@ -286,6 +298,9 @@ gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
else
GST_INFO(0, "invalid mapsize, must a multiple of pagesize, which is %d\n",src->pagesize);
break;
+ case ARG_TOUCH:
+ src->touch = g_value_get_boolean (value);
+ break;
default:
break;
}
@@ -320,6 +335,9 @@ gst_filesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
case ARG_MAPSIZE:
g_value_set_ulong (value, src->mapsize);
break;
+ case ARG_TOUCH:
+ g_value_set_boolean (value, src->touch);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -331,7 +349,7 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
{
GstFileSrc *src = GST_FILESRC(GST_BUFFER_POOL_PRIVATE(buf));
- // fprintf(stderr,"freeing mmap()d buffer at %d+%d\n",GST_BUFFER_OFFSET(buf),GST_BUFFER_SIZE(buf));
+ fs_print ("freeing mmap()d buffer at %d+%d\n",GST_BUFFER_OFFSET(buf),GST_BUFFER_SIZE(buf));
// remove the buffer from the list of available mmap'd regions
g_mutex_lock(src->map_regions_lock);
@@ -347,21 +365,24 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
}
static GstBuffer *
-gst_filesrc_map_region (GstFileSrc *src, off_t offset, off_t size)
+gst_filesrc_map_region (GstFileSrc *src, off_t offset, size_t size)
{
GstBuffer *buf;
gint retval;
-// fprintf(stderr,"mapping region %d+%d from file into memory\n",offset,size);
+ g_return_val_if_fail (offset >= 0, NULL);
+
+ fs_print ("mapping region %08lx+%08lx from file into memory\n",offset,size);
// time to allocate a new mapbuf
buf = gst_buffer_new();
// mmap() the data into this new buffer
GST_BUFFER_DATA(buf) = mmap (NULL, size, PROT_READ, MAP_SHARED, src->fd, offset);
if (GST_BUFFER_DATA(buf) == NULL) {
- fprintf(stderr, "ERROR: gstfilesrc couldn't map file!\n");
- } else if (GST_BUFFER_DATA(buf) == (void *)-1) {
- perror("gstfilesrc:mmap()");
+ fprintf (stderr, "ERROR: gstfilesrc couldn't map file!\n");
+ } else if (GST_BUFFER_DATA(buf) == MAP_FAILED) {
+ g_error ("gstfilesrc mmap(0x%x, %d, 0x%llx) : %s",
+ size, src->fd, offset, sys_errlist[errno]);
}
// madvise to tell the kernel what to do with it
retval = madvise(GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf),MADV_SEQUENTIAL);
@@ -382,20 +403,27 @@ gst_filesrc_map_region (GstFileSrc *src, off_t offset, off_t size)
}
static GstBuffer *
-gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, off_t size)
+gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, size_t size)
{
- int mod, mapbase, mapsize;
+ size_t mapsize;
+ off_t mod, mapbase;
GstBuffer *map;
// printf("attempting to map a small buffer at %d+%d\n",offset,size);
// if the offset starts at a non-page boundary, we have to special case
if ((mod = offset % src->pagesize)) {
+ GstBuffer *ret;
+
mapbase = offset - mod;
mapsize = ((size + mod + src->pagesize - 1) / src->pagesize) * src->pagesize;
// printf("not on page boundaries, resizing map to %d+%d\n",mapbase,mapsize);
map = gst_filesrc_map_region(src, mapbase, mapsize);
- return gst_buffer_create_sub (map, offset - mapbase, size);
+ ret = gst_buffer_create_sub (map, offset - mapbase, size);
+
+ gst_buffer_unref (map);
+
+ return ret;
}
return gst_filesrc_map_region(src,offset,size);
@@ -431,8 +459,8 @@ gst_filesrc_get (GstPad *pad)
{
GstFileSrc *src;
GstBuffer *buf = NULL, *map;
- off_t readend,readsize,mapstart,mapend;
- gboolean eof = FALSE;
+ size_t readsize;
+ off_t readend,mapstart,mapend;
GstFileSrcRegion region;
int i;
@@ -440,6 +468,18 @@ gst_filesrc_get (GstPad *pad)
src = GST_FILESRC (gst_pad_get_parent (pad));
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN), NULL);
+ // check for seek
+ if (src->seek_happened) {
+ src->seek_happened = FALSE;
+ return gst_event_new(GST_EVENT_DISCONTINUOUS);
+ }
+
+ // check for EOF
+ if (src->curoffset == src->filelen) {
+ gst_element_set_state(src,GST_STATE_PAUSED);
+ return gst_event_new(GST_EVENT_EOS);
+ }
+
// calculate end pointers so we don't have to do so repeatedly later
readsize = src->block_size;
readend = src->curoffset + src->block_size; // note this is the byte *after* the read
@@ -450,7 +490,6 @@ gst_filesrc_get (GstPad *pad)
if (readend > src->filelen) {
readsize = src->filelen - src->curoffset;
readend = src->curoffset;
- eof = TRUE;
}
// if the start is past the mapstart
@@ -458,15 +497,15 @@ gst_filesrc_get (GstPad *pad)
// if the end is before the mapend, the buffer is in current mmap region...
// ('cause by definition if readend is in the buffer, so's readstart)
if (readend <= mapend) {
-// printf("read buf %d+%d lives in current mapbuf %d+%d, creating subbuffer of mapbuf\n",
-// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
+ fs_print ("read buf %d+%d lives in current mapbuf %d+%d, creating subbuffer of mapbuf\n",
+ src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
buf = gst_buffer_create_sub (src->mapbuf, src->curoffset - GST_BUFFER_OFFSET(src->mapbuf),
readsize);
// if the start actually is within the current mmap region, map an overlap buffer
} else if (src->curoffset < mapend) {
-// printf("read buf %d+%d starts in mapbuf %d+%d but ends outside, creating new mmap\n",
-// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
+ fs_print ("read buf %d+%d starts in mapbuf %d+%d but ends outside, creating new mmap\n",
+ src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
}
@@ -478,37 +517,39 @@ gst_filesrc_get (GstPad *pad)
// either the read buffer overlaps the start of the mmap region
// or the read buffer fully contains the current mmap region
// either way, it's really not relevant, we just create a new region anyway
-// printf("read buf %d+%d starts before mapbuf %d+%d, but overlaps it\n",
-// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
+ fs_print ("read buf %d+%d starts before mapbuf %d+%d, but overlaps it\n",
+ src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
}
// then deal with the case where the read buffer is totally outside
if (buf == NULL) {
// first check to see if there's a map that covers the right region already
-// printf("searching for mapbuf to cover %d+%d\n",src->curoffset,readsize);
+ fs_print ("searching for mapbuf to cover %d+%d\n",src->curoffset,readsize);
region.offset = src->curoffset;
region.size = readsize;
- map = g_tree_search(src->map_regions,gst_filesrc_search_region_match,®ion);
+ map = g_tree_search (src->map_regions,
+ (GCompareFunc) gst_filesrc_search_region_match,
+ ®ion);
// if we found an exact match, subbuffer it
if (map != NULL) {
-// printf("found mapbuf at %d+%d, creating subbuffer\n",GST_BUFFER_OFFSET(map),GST_BUFFER_SIZE(map));
+ fs_print ("found mapbuf at %d+%d, creating subbuffer\n",GST_BUFFER_OFFSET(map),GST_BUFFER_SIZE(map));
buf = gst_buffer_create_sub (map, src->curoffset - GST_BUFFER_OFFSET(map), readsize);
// otherwise we need to create something out of thin air
} else {
// if the read buffer crosses a mmap region boundary, create a one-off region
if ((src->curoffset / src->mapsize) != (readend / src->mapsize)) {
-// printf("read buf %d+%d crosses a %d-byte boundary, creating a one-off\n",
-// src->curoffset,readsize,src->mapsize);
+ fs_print ("read buf %d+%d crosses a %d-byte boundary, creating a one-off\n",
+ src->curoffset,readsize,src->mapsize);
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
// otherwise we will create a new mmap region and set it to the default
} else {
off_t nextmap = src->curoffset - (src->curoffset % src->mapsize);
-// printf("read buf %d+%d in new mapbuf at %d+%d, mapping and subbuffering\n",
-// src->curoffset,readsize,nextmap,src->mapsize);
+ fs_print ("read buf %d+%d in new mapbuf at %d+%d, mapping and subbuffering\n",
+ src->curoffset,readsize,nextmap,src->mapsize);
// first, we're done with the old mapbuf
gst_buffer_unref(src->mapbuf);
// create a new one
@@ -525,8 +566,6 @@ gst_filesrc_get (GstPad *pad)
*(GST_BUFFER_DATA(buf)+i) = *(GST_BUFFER_DATA(buf)+i);
}
- // if we hit EOF,
-
/* we're done, return the buffer */
src->curoffset += GST_BUFFER_SIZE(buf);
return buf;
@@ -567,6 +606,7 @@ gst_filesrc_close_file (GstFileSrc *src)
{
g_return_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN));
+ g_print ("close\n");
/* close the file */
close (src->fd);
@@ -613,6 +653,7 @@ gst_filesrc_srcpad_event(GstPad *pad, GstEventType event, gint64 location, guint
} else if (data == SEEK_END) {
src->curoffset = src->filelen - (guint64)location;
}
+ src->seek_happened = TRUE;
// push a discontinuous event?
return TRUE;
}
diff --git a/plugins/elements/gstsinesrc.c b/plugins/elements/gstsinesrc.c
new file mode 100644
index 0000000000..75ca6ba3b9
--- /dev/null
+++ b/plugins/elements/gstsinesrc.c
@@ -0,0 +1,452 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ * 2001 Steve Baker
+ *
+ * gstsinesrc.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include
+#include
+#include
+
+#include
+
+
+GstElementDetails gst_sinesrc_details = {
+ "Sine-wave src",
+ "Source/Audio",
+ "Create a sine wave of a given frequency and volume",
+ VERSION,
+ "Erik Walthinsen ",
+ "(C) 1999",
+};
+
+
+/* SineSrc signals and args */
+enum {
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum {
+ ARG_0,
+ ARG_VOLUME,
+ ARG_FORMAT,
+ ARG_SAMPLERATE,
+ ARG_FREQ,
+ ARG_TABLESIZE,
+ ARG_BUFFER_SIZE,
+};
+
+// FIXME: this is not core business...
+GST_PADTEMPLATE_FACTORY (sinesrc_src_factory,
+ "src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_CAPS_NEW (
+ "sinesrc_src",
+ "audio/raw",
+ "format", GST_PROPS_STRING ("int"),
+ "law", GST_PROPS_INT (0),
+ "endianness", GST_PROPS_INT (G_BYTE_ORDER),
+ "signed", GST_PROPS_BOOLEAN (TRUE),
+ "width", GST_PROPS_INT (16),
+ "depth", GST_PROPS_INT (16),
+ "rate", GST_PROPS_INT_RANGE (8000, 48000),
+ "channels", GST_PROPS_INT (1)
+ )
+);
+
+static void gst_sinesrc_class_init (GstSineSrcClass *klass);
+static void gst_sinesrc_init (GstSineSrc *src);
+static GstPadNegotiateReturn gst_sinesrc_negotiate (GstPad *pad, GstCaps **caps, gpointer *data);
+static void gst_sinesrc_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static void gst_sinesrc_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+//static gboolean gst_sinesrc_change_state(GstElement *element,
+// GstElementState state);
+//static void gst_sinesrc_close_audio(GstSineSrc *src);
+//static gboolean gst_sinesrc_open_audio(GstSineSrc *src);
+
+static void gst_sinesrc_update_volume(GValue *value, gpointer data);
+static void gst_sinesrc_update_freq(GValue *value, gpointer data);
+static void gst_sinesrc_populate_sinetable (GstSineSrc *src);
+static inline void gst_sinesrc_update_table_inc (GstSineSrc *src);
+static inline void gst_sinesrc_update_vol_scale (GstSineSrc *src);
+static void gst_sinesrc_force_caps (GstSineSrc *src);
+
+static GstBuffer* gst_sinesrc_get (GstPad *pad);
+
+static GstElementClass *parent_class = NULL;
+//static guint gst_sinesrc_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_sinesrc_get_type (void)
+{
+ static GType sinesrc_type = 0;
+
+ if (!sinesrc_type) {
+ static const GTypeInfo sinesrc_info = {
+ sizeof(GstSineSrcClass),
+ NULL,
+ NULL,
+ (GClassInitFunc)gst_sinesrc_class_init,
+ NULL,
+ NULL,
+ sizeof(GstSineSrc),
+ 0,
+ (GInstanceInitFunc)gst_sinesrc_init,
+ };
+ sinesrc_type = g_type_register_static (GST_TYPE_ELEMENT, "GstSineSrc", &sinesrc_info, 0);
+ }
+ return sinesrc_type;
+}
+
+static void
+gst_sinesrc_class_init (GstSineSrcClass *klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+
+ gobject_class = (GObjectClass*)klass;
+ gstelement_class = (GstElementClass*)klass;
+
+ parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
+
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VOLUME,
+ g_param_spec_double("volume","volume","volume",
+ 0.0, 1.0, 0.0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FORMAT,
+ g_param_spec_int("format","format","format",
+ G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SAMPLERATE,
+ g_param_spec_int("samplerate","samplerate","samplerate",
+ G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TABLESIZE,
+ g_param_spec_int("tablesize","tablesize","tablesize",
+ G_MININT,G_MAXINT,0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_FREQ,
+ g_param_spec_double("freq","freq","freq",
+ 0.0,G_MAXDOUBLE, 440.0,G_PARAM_READWRITE)); // CHECKME
+ g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFFER_SIZE,
+ g_param_spec_int("buffersize","buffersize","buffersize",
+ 0, G_MAXINT, 1024, G_PARAM_READWRITE));
+
+ gobject_class->set_property = gst_sinesrc_set_property;
+ gobject_class->get_property = gst_sinesrc_get_property;
+
+// gstelement_class->change_state = gst_sinesrc_change_state;
+}
+
+static void
+gst_sinesrc_init (GstSineSrc *src)
+{
+ GstElement *element = GST_ELEMENT(src);
+ GstDParamManager *dpman;
+
+ src->srcpad = gst_pad_new_from_template (
+ GST_PADTEMPLATE_GET (sinesrc_src_factory), "src");
+ gst_element_add_pad(GST_ELEMENT(src), src->srcpad);
+ gst_pad_set_negotiate_function (src->srcpad, gst_sinesrc_negotiate);
+
+ gst_pad_set_get_function(src->srcpad, gst_sinesrc_get);
+
+ src->format = 16;
+ src->samplerate = 44100;
+
+ src->newcaps = TRUE;
+
+ src->table_pos = 0.0;
+ src->table_size = 1024;
+ src->buffer_size=1024;
+
+ src->seq = 0;
+
+ dpman = gst_dpman_new ("sinesrc_dpman", GST_ELEMENT(src));
+ gst_dpman_add_required_dparam (dpman, "volume", G_TYPE_FLOAT, gst_sinesrc_update_volume, src);
+ gst_dpman_add_required_dparam (dpman, "freq", G_TYPE_FLOAT, gst_sinesrc_update_freq, src);
+
+ gst_dpman_set_rate_change_pad(dpman, src->srcpad);
+
+ GST_ELEMENT_DPARAM_MANAGER(element) = dpman;
+
+ gst_sinesrc_update_vol_scale(src);
+
+ gst_sinesrc_populate_sinetable(src);
+ gst_sinesrc_update_table_inc(src);
+
+}
+
+static GstPadNegotiateReturn
+gst_sinesrc_negotiate (GstPad *pad, GstCaps **caps, gpointer *data)
+{
+ GstSineSrc *src;
+
+ if (*caps) {
+ g_return_val_if_fail (pad != NULL, GST_PAD_NEGOTIATE_FAIL);
+ src = GST_SINESRC(gst_pad_get_parent (pad));
+ src->samplerate = gst_caps_get_int (*caps, "rate");
+ gst_sinesrc_update_table_inc(src);
+ return GST_PAD_NEGOTIATE_AGREE;
+ }
+
+ return GST_PAD_NEGOTIATE_FAIL;
+}
+
+static GstBuffer *
+gst_sinesrc_get(GstPad *pad)
+{
+ GstSineSrc *src;
+ GstBuffer *buf;
+ GstDParamManager *dpman;
+
+ gint16 *samples;
+ gint i=0, frame_countdown;
+
+ g_return_val_if_fail (pad != NULL, NULL);
+ src = GST_SINESRC(gst_pad_get_parent (pad));
+
+ buf = gst_buffer_new();
+ g_return_val_if_fail (buf, NULL);
+ samples = g_new(gint16, src->buffer_size);
+ GST_BUFFER_DATA(buf) = (gpointer) samples;
+ GST_BUFFER_SIZE(buf) = 2 * src->buffer_size;
+
+ dpman = GST_ELEMENT_DPARAM_MANAGER(GST_ELEMENT(src));
+ frame_countdown = GST_DPMAN_FIRST_COUNTDOWN(dpman, src->buffer_size, 0LL);
+
+ while(GST_DPMAN_COUNTDOWN(dpman, frame_countdown, i)) {
+ src->table_lookup = (gint)(src->table_pos);
+ src->table_lookup_next = src->table_lookup + 1;
+ src->table_interp = src->table_pos - src->table_lookup;
+
+ // wrap the array lookups if we're out of bounds
+ if (src->table_lookup_next >= src->table_size){
+ src->table_lookup_next -= src->table_size;
+ if (src->table_lookup >= src->table_size){
+ src->table_lookup -= src->table_size;
+ src->table_pos -= src->table_size;
+ }
+ }
+
+ src->table_pos += src->table_inc;
+
+ //no interpolation
+ //samples[i] = src->table_data[src->table_lookup]
+ // * src->vol_scale;
+
+ //linear interpolation
+ samples[i++] = ((src->table_interp
+ *(src->table_data[src->table_lookup_next]
+ -src->table_data[src->table_lookup]
+ )
+ )+src->table_data[src->table_lookup]
+ )* src->vol_scale;
+ }
+
+ if (src->newcaps) {
+ gst_sinesrc_force_caps(src);
+ }
+
+ return buf;
+}
+
+static void
+gst_sinesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GstSineSrc *src;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_SINESRC(object));
+ src = GST_SINESRC(object);
+
+ switch (prop_id) {
+ case ARG_VOLUME:
+ src->volume = (gfloat)g_value_get_double (value);
+ gst_sinesrc_update_vol_scale(src);
+ break;
+ case ARG_FORMAT:
+ src->format = g_value_get_int (value);
+ src->newcaps=TRUE;
+ break;
+ case ARG_SAMPLERATE:
+ src->samplerate = g_value_get_int (value);
+ src->newcaps=TRUE;
+ gst_sinesrc_update_table_inc(src);
+ break;
+ case ARG_FREQ: {
+ if (g_value_get_double (value) <= 0.0 || g_value_get_double (value) > src->samplerate/2)
+ break;
+ src->freq = (gfloat)g_value_get_double (value);
+ gst_sinesrc_update_table_inc(src);
+ break;
+ case ARG_TABLESIZE:
+ src->table_size = g_value_get_int (value);
+ gst_sinesrc_populate_sinetable(src);
+ gst_sinesrc_update_table_inc(src);
+ break;
+ case ARG_BUFFER_SIZE:
+ src->buffer_size = g_value_get_int (value);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void
+gst_sinesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GstSineSrc *src;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail(GST_IS_SINESRC(object));
+ src = GST_SINESRC(object);
+
+ switch (prop_id) {
+ case ARG_VOLUME:
+ g_value_set_double (value, (gdouble)(src->volume));
+ break;
+ case ARG_FORMAT:
+ g_value_set_int (value, src->format);
+ break;
+ case ARG_SAMPLERATE:
+ g_value_set_int (value, src->samplerate);
+ break;
+ case ARG_FREQ:
+ g_value_set_double (value, (gdouble)(src->freq));
+ break;
+ case ARG_TABLESIZE:
+ g_value_set_int (value, src->table_size);
+ break;
+ case ARG_BUFFER_SIZE:
+ g_value_set_int (value, src->buffer_size);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/*
+static gboolean gst_sinesrc_change_state(GstElement *element,
+ GstElementState state) {
+ g_return_if_fail(GST_IS_SINESRC(element));
+
+ switch (state) {
+ case GST_STATE_RUNNING:
+ if (!gst_sinesrc_open_audio(GST_SINESRC(element)))
+ return FALSE;
+ break;
+ case ~GST_STATE_RUNNING:
+ gst_sinesrc_close_audio(GST_SINESRC(element));
+ break;
+ default:
+ break;
+ }
+
+ if (GST_ELEMENT_CLASS(parent_class)->change_state)
+ return GST_ELEMENT_CLASS(parent_class)->change_state(element,state);
+ return TRUE;
+}
+*/
+
+static void
+gst_sinesrc_populate_sinetable (GstSineSrc *src)
+{
+ gint i;
+ gdouble pi2scaled = M_PI * 2 / src->table_size;
+ gfloat *table = g_new(gfloat, src->table_size);
+
+ for(i=0 ; i < src->table_size ; i++){
+ table[i] = (gfloat)sin(i * pi2scaled);
+ }
+
+ g_free(src->table_data);
+ src->table_data = table;
+}
+
+static void
+gst_sinesrc_update_volume(GValue *value, gpointer data)
+{
+ GstSineSrc *src = (GstSineSrc*)data;
+ g_return_if_fail(GST_IS_SINESRC(src));
+
+ src->volume = g_value_get_float(value);
+ src->vol_scale = 32767.0 * src->volume;
+}
+
+static void
+gst_sinesrc_update_freq(GValue *value, gpointer data)
+{
+ GstSineSrc *src = (GstSineSrc*)data;
+ g_return_if_fail(GST_IS_SINESRC(src));
+
+ src->freq = g_value_get_float(value);
+ src->table_inc = src->table_size * src->freq / src->samplerate;
+}
+
+static inline void
+gst_sinesrc_update_table_inc (GstSineSrc *src)
+{
+ src->table_inc = src->table_size * src->freq / src->samplerate;
+}
+
+static inline void
+gst_sinesrc_update_vol_scale (GstSineSrc *src)
+{
+ src->vol_scale = 32767.0 * src->volume;
+}
+
+static void
+gst_sinesrc_force_caps(GstSineSrc *src) {
+ GstCaps *caps;
+
+ if (!src->newcaps)
+ return;
+
+ src->newcaps=FALSE;
+
+ caps = gst_caps_new (
+ "sinesrc_src_caps",
+ "audio/raw",
+ gst_props_new (
+ "format", GST_PROPS_STRING ("int"),
+ "law", GST_PROPS_INT (0),
+ "endianness", GST_PROPS_INT (G_BYTE_ORDER),
+ "signed", GST_PROPS_BOOLEAN (TRUE),
+ "width", GST_PROPS_INT (16),
+ "depth", GST_PROPS_INT (16),
+ "rate", GST_PROPS_INT (src->samplerate),
+ "channels", GST_PROPS_INT (1),
+ NULL
+ )
+ );
+
+ gst_pad_set_caps (src->srcpad, caps);
+}
+
+gboolean
+gst_sinesrc_factory_init (GstElementFactory *factory)
+{
+ gst_elementfactory_add_padtemplate (factory, GST_PADTEMPLATE_GET (sinesrc_src_factory));
+
+ return TRUE;
+}
diff --git a/plugins/elements/gstsinesrc.h b/plugins/elements/gstsinesrc.h
new file mode 100644
index 0000000000..58e03fd72b
--- /dev/null
+++ b/plugins/elements/gstsinesrc.h
@@ -0,0 +1,96 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstsinesrc.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_SINESRC_H__
+#define __GST_SINESRC_H__
+
+
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+GstElementDetails gst_sinesrc_details;
+
+
+#define GST_TYPE_SINESRC \
+ (gst_sinesrc_get_type())
+#define GST_SINESRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SINESRC,GstSineSrc))
+#define GST_SINESRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SINESRC,GstSineSrcClass))
+#define GST_IS_SINESRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SINESRC))
+#define GST_IS_SINESRC_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SINESRC))
+
+typedef struct _GstSineSrc GstSineSrc;
+typedef struct _GstSineSrcClass GstSineSrcClass;
+
+struct _GstSineSrc {
+ GstElement element;
+
+ /* pads */
+ GstPad *srcpad;
+
+ /* parameters */
+ gfloat volume;
+ gfloat freq;
+ gfloat vol_scale;
+
+ /* lookup table data */
+ gfloat *table_data;
+ gdouble table_pos;
+ gdouble table_inc;
+ gint table_size;
+ gdouble table_interp;
+ gint table_lookup;
+ gint table_lookup_next;
+
+ /* audio parameters */
+ gint format;
+ gint samplerate;
+
+ gint buffer_size;
+ gulong seq;
+
+ gboolean newcaps;
+
+};
+
+struct _GstSineSrcClass {
+ GstElementClass parent_class;
+};
+
+GType gst_sinesrc_get_type(void);
+gboolean gst_sinesrc_factory_init (GstElementFactory *factory);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_SINESRC_H__ */
diff --git a/plugins/elements/gsttee.c b/plugins/elements/gsttee.c
index 729b95ec03..d7e0544bb0 100644
--- a/plugins/elements/gsttee.c
+++ b/plugins/elements/gsttee.c
@@ -56,7 +56,7 @@ GST_PADTEMPLATE_FACTORY (tee_src_factory,
static void gst_tee_class_init (GstTeeClass *klass);
static void gst_tee_init (GstTee *tee);
-static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp);
+static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp, const gchar *unused);
static void gst_tee_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec);
@@ -127,7 +127,7 @@ gst_tee_init (GstTee *tee)
}
static GstPad*
-gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ)
+gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
{
gchar *name;
GstPad *srcpad;
diff --git a/test/ac3play.c b/test/ac3play.c
index 292440e2a9..23f6fa7890 100644
--- a/test/ac3play.c
+++ b/test/ac3play.c
@@ -55,7 +55,9 @@ int main(int argc,char *argv[]) {
gst_pad_connect(gst_element_get_pad(queue,"src"),
gst_element_get_pad(play,"sink"));
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("ac3play.gst", gst_xml_write(GST_ELEMENT(pipeline)));
+#endif
// set thread start state
g_object_set(G_OBJECT(decodethread),"create_thread",TRUE,NULL);
diff --git a/test/aviparse.c b/test/aviparse.c
index 1cb43138d3..44f876acf2 100644
--- a/test/aviparse.c
+++ b/test/aviparse.c
@@ -128,7 +128,9 @@ int main(int argc,char *argv[]) {
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_READY);
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("aviparse.xml",gst_xml_write(GST_ELEMENT(pipeline)));
+#endif
g_print("about to enter loop\n");
diff --git a/test/bufspeed/.gitignore b/test/bufspeed/.gitignore
new file mode 100644
index 0000000000..25d1705737
--- /dev/null
+++ b/test/bufspeed/.gitignore
@@ -0,0 +1,10 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+*.xml
+test1
+test2
diff --git a/test/bufspeed/Makefile.am b/test/bufspeed/Makefile.am
new file mode 100644
index 0000000000..e86b7a7699
--- /dev/null
+++ b/test/bufspeed/Makefile.am
@@ -0,0 +1,6 @@
+noinst_PROGRAMS = test1 test2
+
+test1_SOURCES = test1.c gstbuffer.c gstmempool.c
+
+#LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
diff --git a/test/bufspeed/README b/test/bufspeed/README
new file mode 100644
index 0000000000..8bb6600a9f
--- /dev/null
+++ b/test/bufspeed/README
@@ -0,0 +1,6 @@
+benchmark of 5000000 gst_buffer_new/free on 0.2.1 code
+------------------------------------------------------
+gstmemchunk, no lock: real 0m1.309s user 0m1.220s sys 0m0.070s
+gmemchunk, no lock: real 0m3.872s user 0m3.740s sys 0m0.090s
+gstmemchunk, lock: real 0m5.306s user 0m5.160s sys 0m0.100s
+gmemchunk, lock: real 0m8.001s user 0m7.890s sys 0m0.080s
diff --git a/test/bufspeed/gstbuffer.c b/test/bufspeed/gstbuffer.c
new file mode 100644
index 0000000000..35a92ee90a
--- /dev/null
+++ b/test/bufspeed/gstbuffer.c
@@ -0,0 +1,495 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstbuffer.c: Buffer operations
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* this file makes too much noise for most debugging sessions */
+#define GST_DEBUG_FORCE_DISABLE
+#include "gst/gst_private.h"
+
+#include "gstbuffer.h"
+#include "gstmempool.h"
+
+GType _gst_buffer_type;
+
+static GstMemPool *_gst_buffer_pool;
+
+static void
+gst_buffer_alloc_func (GstMemPool *pool, gpointer data)
+{
+ GstBuffer *buffer = GST_BUFFER (data);
+
+ GST_DATA_TYPE(buffer) = _gst_buffer_type;
+ buffer->lock = g_mutex_new ();
+}
+
+static void
+gst_buffer_free_func (GstMemPool *pool, gpointer data)
+{
+ GstBuffer *buffer = GST_BUFFER (data);
+
+ g_mutex_free (buffer->lock);
+}
+
+void
+_gst_buffer_initialize (void)
+{
+ int buffersize = sizeof(GstBuffer);
+ static const GTypeInfo buffer_info = {
+ 0, // sizeof(class),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0, // sizeof(object),
+ 0,
+ NULL,
+ };
+
+ // round up to the nearest 32 bytes for cache-line and other efficiencies
+ buffersize = (((buffersize-1) / 32) + 1) * 32;
+
+ _gst_buffer_pool = gst_mem_pool_new ("GstBuffer", buffersize,
+ buffersize * 32, G_ALLOC_AND_FREE, gst_buffer_alloc_func, gst_buffer_free_func);
+
+ _gst_buffer_type = g_type_register_static (G_TYPE_INT, "GstBuffer", &buffer_info, 0);
+}
+
+/**
+ * gst_buffer_new:
+ *
+ * Create a new buffer.
+ *
+ * Returns: new buffer
+ */
+GstBuffer*
+gst_buffer_new (void)
+{
+ GstBuffer *buffer;
+
+ buffer = gst_mem_pool_alloc (_gst_buffer_pool);
+
+ GST_INFO (GST_CAT_BUFFER,"creating new buffer %p",buffer);
+
+#ifdef HAVE_ATOMIC_H
+ atomic_set (&buffer->refcount, 1);
+#else
+ buffer->refcount = 1;
+#endif
+ buffer->offset = -1;
+ buffer->flags = 0;
+ buffer->data = NULL;
+ buffer->size = 0;
+ buffer->maxsize = 0;
+ buffer->timestamp = 0;
+ buffer->parent = NULL;
+ buffer->pool = NULL;
+ buffer->pool_private = NULL;
+ buffer->free = NULL;
+ buffer->copy = NULL;
+
+ return buffer;
+}
+
+/**
+ * gst_buffer_new_from_pool:
+ * @pool: the buffer pool to use
+ *
+ * Create a new buffer using the specified bufferpool.
+ *
+ * Returns: new buffer
+ */
+GstBuffer*
+gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size)
+{
+ GstBuffer *buffer;
+
+ g_return_val_if_fail (pool != NULL, NULL);
+ g_return_val_if_fail (pool->buffer_new != NULL, NULL);
+
+ buffer = pool->buffer_new (pool, offset, size, pool->user_data);
+ buffer->pool = pool;
+ buffer->free = pool->buffer_free;
+ buffer->copy = pool->buffer_copy;
+
+ GST_INFO (GST_CAT_BUFFER,"creating new buffer %p from pool %p (size %x, offset %x)",
+ buffer, pool, size, offset);
+
+ return buffer;
+}
+
+/**
+ * gst_buffer_create_sub:
+ * @parent: parent buffer
+ * @offset: offset into parent buffer
+ * @size: size of new subbuffer
+ *
+ * Creates a sub-buffer from the parent at a given offset.
+ *
+ * Returns: new buffer
+ */
+GstBuffer*
+gst_buffer_create_sub (GstBuffer *parent,
+ guint32 offset,
+ guint32 size)
+{
+ GstBuffer *buffer;
+
+ g_return_val_if_fail (parent != NULL, NULL);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(parent) > 0, NULL);
+ g_return_val_if_fail (size > 0, NULL);
+ g_return_val_if_fail ((offset+size) <= parent->size, NULL);
+
+ buffer = gst_mem_pool_alloc (_gst_buffer_pool);
+ GST_DATA_TYPE(buffer) = _gst_buffer_type;
+
+ GST_INFO (GST_CAT_BUFFER,"creating new subbuffer %p from parent %p (size %u, offset %u)",
+ buffer, parent, size, offset);
+
+#ifdef HAVE_ATOMIC_H
+ atomic_set (&buffer->refcount, 1);
+#else
+ buffer->refcount = 1;
+#endif
+
+ // copy flags and type from parent, for lack of better
+ buffer->flags = parent->flags;
+
+ // set the data pointer, size, offset, and maxsize
+ buffer->data = parent->data + offset;
+ buffer->size = size;
+ buffer->maxsize = parent->size - offset;
+
+ // deal with bogus/unknown offsets
+ if (parent->offset != -1)
+ buffer->offset = parent->offset + offset;
+ else
+ buffer->offset = -1;
+
+ // again, for lack of better, copy parent's timestamp
+ buffer->timestamp = parent->timestamp;
+ buffer->maxage = parent->maxage;
+
+ // if the parent buffer is a subbuffer itself, use its parent, a real buffer
+ if (parent->parent != NULL)
+ parent = parent->parent;
+
+ // set parentage and reference the parent
+ buffer->parent = parent;
+ gst_buffer_ref (parent);
+
+ buffer->pool = NULL;
+
+ return buffer;
+}
+
+
+// FIXME FIXME: how does this overlap with the newly-added gst_buffer_span() ???
+/**
+ * gst_buffer_append:
+ * @buffer: a buffer
+ * @append: the buffer to append
+ *
+ * Creates a new buffer by appending the data of append to the
+ * existing data of buffer.
+ *
+ * Returns: new buffer
+ */
+GstBuffer*
+gst_buffer_append (GstBuffer *buffer,
+ GstBuffer *append)
+{
+ guint size;
+ GstBuffer *newbuf;
+
+ g_return_val_if_fail (buffer != NULL, NULL);
+ g_return_val_if_fail (append != NULL, NULL);
+ g_return_val_if_fail (buffer->pool == NULL, NULL);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0, NULL);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(append) > 0, NULL);
+
+ GST_INFO (GST_CAT_BUFFER,"appending buffers %p and %p",buffer,append);
+
+ GST_BUFFER_LOCK (buffer);
+ // the buffer is not used by anyone else
+ if (GST_BUFFER_REFCOUNT (buffer) == 1 && buffer->parent == NULL
+ && !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_DONTFREE)) {
+ // save the old size
+ size = buffer->size;
+ buffer->size += append->size;
+ buffer->data = g_realloc (buffer->data, buffer->size);
+ memcpy(buffer->data + size, append->data, append->size);
+ GST_BUFFER_UNLOCK (buffer);
+ }
+ // the buffer is used, create a new one
+ else {
+ newbuf = gst_buffer_new ();
+ newbuf->size = buffer->size+append->size;
+ newbuf->data = g_malloc (newbuf->size);
+ memcpy (newbuf->data, buffer->data, buffer->size);
+ memcpy (newbuf->data+buffer->size, append->data, append->size);
+ GST_BUFFER_UNLOCK (buffer);
+ gst_buffer_unref (buffer);
+ buffer = newbuf;
+ }
+ return buffer;
+}
+
+/**
+ * gst_buffer_destroy:
+ * @buffer: the GstBuffer to destroy
+ *
+ * destroy the buffer
+ */
+void
+gst_buffer_destroy (GstBuffer *buffer)
+{
+
+ g_return_if_fail (buffer != NULL);
+
+ GST_INFO (GST_CAT_BUFFER, "freeing %sbuffer %p",
+ (buffer->parent?"sub":""),
+ buffer);
+
+ // free the data only if there is some, DONTFREE isn't set, and not sub
+ if (GST_BUFFER_DATA (buffer) &&
+ !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_DONTFREE) &&
+ (buffer->parent == NULL)) {
+ // if there's a free function, use it
+ if (buffer->free != NULL) {
+ (buffer->free)(buffer);
+ } else {
+ g_free (GST_BUFFER_DATA (buffer));
+ }
+ }
+
+ // unreference the parent if there is one
+ if (buffer->parent != NULL)
+ gst_buffer_unref (buffer->parent);
+
+ // remove it entirely from memory
+ gst_mem_pool_free (_gst_buffer_pool,buffer);
+}
+
+/**
+ * gst_buffer_ref:
+ * @buffer: the GstBuffer to reference
+ *
+ * Increment the refcount of this buffer.
+ */
+void
+gst_buffer_ref (GstBuffer *buffer)
+{
+ g_return_if_fail (buffer != NULL);
+ g_return_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0);
+
+ GST_INFO (GST_CAT_BUFFER, "ref buffer %p\n", buffer);
+
+#ifdef HAVE_ATOMIC_H
+ atomic_inc (&(buffer->refcount));
+#else
+ GST_BUFFER_LOCK (buffer);
+ buffer->refcount++;
+ GST_BUFFER_UNLOCK (buffer);
+#endif
+}
+
+/**
+ * gst_buffer_unref:
+ * @buffer: the GstBuffer to unref
+ *
+ * Decrement the refcount of this buffer. If the refcount is
+ * zero, the buffer will be destroyed.
+ */
+void
+gst_buffer_unref (GstBuffer *buffer)
+{
+ gint zero;
+
+ g_return_if_fail (buffer != NULL);
+ g_return_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0);
+
+ GST_INFO (GST_CAT_BUFFER, "unref buffer %p\n", buffer);
+
+#ifdef HAVE_ATOMIC_H
+ zero = atomic_dec_and_test (&(buffer->refcount));
+#else
+ GST_BUFFER_LOCK (buffer);
+ buffer->refcount--;
+ zero = (buffer->refcount == 0);
+ GST_BUFFER_UNLOCK (buffer);
+#endif
+
+ /* if we ended up with the refcount at zero, destroy the buffer */
+ if (zero) {
+ gst_buffer_destroy (buffer);
+ }
+}
+
+/**
+ * gst_buffer_copy:
+ * @buffer: the orignal GstBuffer to make a copy of
+ *
+ * Make a full copy of the give buffer, data and all.
+ *
+ * Returns: new buffer
+ */
+GstBuffer *
+gst_buffer_copy (GstBuffer *buffer)
+{
+ GstBuffer *newbuf;
+
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0, NULL);
+
+ // if a copy function exists, use it, else copy the bytes
+ if (buffer->copy != NULL) {
+ newbuf = (buffer->copy)(buffer);
+ } else {
+ // allocate a new buffer
+ newbuf = gst_buffer_new();
+
+ // copy the absolute size
+ newbuf->size = buffer->size;
+ // allocate space for the copy
+ newbuf->data = (guchar *)g_malloc (buffer->size);
+ // copy the data straight across
+ memcpy(newbuf->data,buffer->data,buffer->size);
+ // the new maxsize is the same as the size, since we just malloc'd it
+ newbuf->maxsize = newbuf->size;
+ }
+ newbuf->offset = buffer->offset;
+ newbuf->timestamp = buffer->timestamp;
+ newbuf->maxage = buffer->maxage;
+
+ // since we just created a new buffer, so we have no ties to old stuff
+ newbuf->parent = NULL;
+ newbuf->pool = NULL;
+
+ return newbuf;
+}
+
+/*
+ * gst_buffer_is_span_fast
+ * @buf1: first source buffer
+ * @buf2: second source buffer
+ *
+ * Determines whether a gst_buffer_span is free, or requires a memcpy.
+ *
+ * Returns: TRUE if the buffers are contiguous, FALSE if a copy would be required.
+ */
+gboolean
+gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
+{
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf1) > 0, FALSE);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf2) > 0, FALSE);
+
+ return (buf1->parent && buf2->parent &&
+ (buf1->parent == buf2->parent) &&
+ ((buf1->data + buf1->size) == buf2->data));
+}
+
+
+/**
+ * gst_buffer_span:
+ * @buf1: first source buffer to merge
+ * @offset: offset in first buffer to start new buffer
+ * @buf2: second source buffer to merge
+ * @len: length of new buffer
+ *
+ * Create a new buffer that consists of part of buf1 and buf2.
+ * Logically, buf1 and buf2 are concatenated into a single larger
+ * buffer, and a new buffer is created at the given offset inside
+ * this space, with a given length.
+ *
+ * If the two source buffers are children of the same larger buffer,
+ * and are contiguous, the new buffer will be a child of the shared
+ * parent, and thus no copying is necessary.
+ *
+ * Returns: new buffer that spans the two source buffers
+ */
+// FIXME need to think about CoW and such...
+GstBuffer *
+gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
+{
+ GstBuffer *newbuf;
+
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf1) > 0, NULL);
+ g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf2) > 0, NULL);
+
+ // make sure buf1 has a lower address than buf2
+ if (buf1->data > buf2->data) {
+ GstBuffer *tmp = buf1;
+ g_print ("swapping buffers\n");
+ buf1 = buf2;
+ buf2 = tmp;
+ }
+
+ // if the two buffers have the same parent and are adjacent
+ if (gst_buffer_is_span_fast(buf1,buf2)) {
+ // we simply create a subbuffer of the common parent
+ newbuf = gst_buffer_create_sub (buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
+ }
+ else {
+ g_print ("slow path taken in buffer_span\n");
+ // otherwise we simply have to brute-force copy the buffers
+ newbuf = gst_buffer_new ();
+
+ // put in new size
+ newbuf->size = len;
+ // allocate space for the copy
+ newbuf->data = (guchar *)g_malloc(len);
+ // copy the first buffer's data across
+ memcpy(newbuf->data, buf1->data + offset, buf1->size - offset);
+ // copy the second buffer's data across
+ memcpy(newbuf->data + (buf1->size - offset), buf2->data, len - (buf1->size - offset));
+
+ if (newbuf->offset != -1)
+ newbuf->offset = buf1->offset + offset;
+ newbuf->timestamp = buf1->timestamp;
+ if (buf2->maxage > buf1->maxage) newbuf->maxage = buf2->maxage;
+ else newbuf->maxage = buf1->maxage;
+
+ }
+
+ return newbuf;
+}
+
+
+/**
+ * gst_buffer_merge:
+ * @buf1: first source buffer to merge
+ * @buf2: second source buffer to merge
+ *
+ * Create a new buffer that is the concatenation of the two source
+ * buffers. The original source buffers will not be modified or
+ * unref'd.
+ *
+ * Internally is nothing more than a specialized gst_buffer_span,
+ * so the same optimizations can occur.
+ *
+ * Returns: new buffer that's the concatenation of the source buffers
+ */
+GstBuffer *
+gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2)
+{
+ // we're just a specific case of the more general gst_buffer_span()
+ return gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
+}
diff --git a/test/bufspeed/gstbuffer.h b/test/bufspeed/gstbuffer.h
new file mode 100644
index 0000000000..d3a5a875b4
--- /dev/null
+++ b/test/bufspeed/gstbuffer.h
@@ -0,0 +1,174 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstbuffer.h: Header for GstBuffer object
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef __GST_BUFFER_H__
+#define __GST_BUFFER_H__
+
+//
+// Define this to add file:line info to each GstBuffer showing
+// the location in the source code where the buffer was created.
+//
+// #define GST_BUFFER_WHERE
+//
+// Then in gdb, you can `call gst_buffer_print_live()' to get a list
+// of allocated GstBuffers and also the file:line where they were
+// allocated.
+//
+
+#include
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ATOMIC_H
+#include
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+extern GType _gst_buffer_type;
+
+#define GST_TYPE_BUFFER (_gst_buffer_type)
+#define GST_BUFFER(buf) ((GstBuffer *)(buf))
+#define GST_IS_BUFFER(buf) (GST_DATA_TYPE(buf) == GST_TYPE_BUFFER)
+
+#define GST_BUFFER_FLAGS(buf) (GST_BUFFER(buf)->flags)
+#define GST_BUFFER_FLAG_IS_SET(buf,flag) (GST_BUFFER_FLAGS(buf) & (1<<(flag)))
+#define GST_BUFFER_FLAG_SET(buf,flag) G_STMT_START{ (GST_BUFFER_FLAGS(buf) |= (1<<(flag))); }G_STMT_END
+#define GST_BUFFER_FLAG_UNSET(buf,flag) G_STMT_START{ (GST_BUFFER_FLAGS(buf) &= ~(1<<(flag))); }G_STMT_END
+
+
+#define GST_BUFFER_DATA(buf) (GST_BUFFER(buf)->data)
+#define GST_BUFFER_SIZE(buf) (GST_BUFFER(buf)->size)
+#define GST_BUFFER_OFFSET(buf) (GST_BUFFER(buf)->offset)
+#define GST_BUFFER_MAXSIZE(buf) (GST_BUFFER(buf)->maxsize)
+#define GST_BUFFER_TIMESTAMP(buf) (GST_BUFFER(buf)->timestamp)
+#define GST_BUFFER_MAXAGE(buf) (GST_BUFFER(buf)->maxage)
+#define GST_BUFFER_BUFFERPOOL(buf) (GST_BUFFER(buf)->pool)
+#define GST_BUFFER_PARENT(buf) (GST_BUFFER(buf)->parent)
+#define GST_BUFFER_POOL_PRIVATE(buf) (GST_BUFFER(buf)->pool_private)
+#define GST_BUFFER_COPY_FUNC(buf) (GST_BUFFER(buf)->copy)
+#define GST_BUFFER_FREE_FUNC(buf) (GST_BUFFER(buf)->free)
+
+
+#define GST_BUFFER_LOCK(buf) (g_mutex_lock(GST_BUFFER(buf)->lock))
+#define GST_BUFFER_TRYLOCK(buf) (g_mutex_trylock(GST_BUFFER(buf)->lock))
+#define GST_BUFFER_UNLOCK(buf) (g_mutex_unlock(GST_BUFFER(buf)->lock))
+
+
+typedef enum {
+ GST_BUFFER_READONLY,
+ GST_BUFFER_ORIGINAL,
+ GST_BUFFER_DONTFREE,
+
+ GST_BUFFER_FLUSH,
+ GST_BUFFER_EOS,
+ GST_BUFFER_DISCONTINUOUS,
+} GstBufferFlags;
+
+
+typedef struct _GstBuffer GstBuffer;
+
+
+typedef void (*GstBufferFreeFunc) (GstBuffer *buf);
+typedef GstBuffer *(*GstBufferCopyFunc) (GstBuffer *srcbuf);
+
+
+#include
+
+struct _GstBuffer {
+ GstData data_type;
+
+ /* locking */
+ GMutex *lock;
+
+ /* refcounting */
+#ifdef HAVE_ATOMIC_H
+ atomic_t refcount;
+#define GST_BUFFER_REFCOUNT(buf) (atomic_read(&(GST_BUFFER((buf))->refcount)))
+#else
+ int refcount;
+#define GST_BUFFER_REFCOUNT(buf) (GST_BUFFER(buf)->refcount)
+#endif
+
+ /* flags */
+ guint16 flags;
+
+ /* pointer to data, its size, and offset in original source if known */
+ guchar *data;
+ guint32 size;
+ guint32 maxsize;
+ guint32 offset;
+
+ /* timestamp */
+ gint64 timestamp;
+ gint64 maxage;
+
+ /* subbuffer support, who's my parent? */
+ GstBuffer *parent;
+
+ /* this is a pointer to the buffer pool (if any) */
+ GstBufferPool *pool;
+ gpointer pool_private;
+
+ /* utility function pointers */
+ GstBufferFreeFunc free; // free the data associated with the buffer
+ GstBufferCopyFunc copy; // copy the data from one buffer to another
+};
+
+/* initialisation */
+void _gst_buffer_initialize (void);
+/* creating a new buffer from scratch */
+GstBuffer* gst_buffer_new (void);
+GstBuffer* gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size);
+
+/* creating a subbuffer */
+GstBuffer* gst_buffer_create_sub (GstBuffer *parent, guint32 offset, guint32 size);
+
+/* refcounting */
+void gst_buffer_ref (GstBuffer *buffer);
+void gst_buffer_unref (GstBuffer *buffer);
+
+/* destroying the buffer */
+void gst_buffer_destroy (GstBuffer *buffer);
+
+/* copy buffer */
+GstBuffer* gst_buffer_copy (GstBuffer *buffer);
+
+/* merge, span, or append two buffers, intelligently */
+GstBuffer* gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2);
+GstBuffer* gst_buffer_span (GstBuffer *buf1,guint32 offset,GstBuffer *buf2,guint32 len);
+GstBuffer* gst_buffer_append (GstBuffer *buf, GstBuffer *buf2);
+
+gboolean gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GST_BUFFER_H__ */
diff --git a/test/bufspeed/gstmempool.c b/test/bufspeed/gstmempool.c
new file mode 100644
index 0000000000..c9f956e6f3
--- /dev/null
+++ b/test/bufspeed/gstmempool.c
@@ -0,0 +1,191 @@
+#include "gstmempool.h"
+
+#ifdef __SMP__
+#define POOL_LOCK "lock ; "
+#else
+#define POOL_LOCK ""
+#endif
+
+#define GST_MEM_POOL_AREA(pool) (((GstMemPoolElement*)(pool))->area)
+#define GST_MEM_POOL_DATA(pool) ((gpointer)(((GstMemPoolElement*)(pool)) + 1))
+#define GST_MEM_POOL_LINK(mem) ((GstMemPoolElement*)((guint8*)(mem) - sizeof (GstMemPoolElement)))
+
+#define USE_ASM
+
+/*******************************************************
+ * area size
+ * +-----------------------------------------+
+ * pool size
+ * +------------+
+ *
+ * !next!data... !next!data.... !next!data...
+ * ! ^ ! ^ !
+ * +-------------+ +------------+ +---> NULL
+ *
+ */
+static gboolean
+populate (GstMemPool *mem_pool)
+{
+ guint8 *area;
+ gint i;
+
+ if (mem_pool->cleanup)
+ return FALSE;
+
+ area = (guint8 *) g_malloc (mem_pool->area_size);
+
+ for (i=0; i < mem_pool->area_size; i += mem_pool->pool_size) {
+ guint8 *areap = area + i;
+
+ GST_MEM_POOL_AREA (areap) = (GstMemPoolElement *)area;
+
+ if (mem_pool->alloc_func) {
+ mem_pool->alloc_func (mem_pool, GST_MEM_POOL_DATA (areap));
+ }
+
+ gst_mem_pool_free (mem_pool, GST_MEM_POOL_DATA (areap));
+ }
+
+ return TRUE;
+}
+
+
+GstMemPool*
+gst_mem_pool_new (gchar* name, gint atom_size, gulong area_size, gint type,
+ GstMemPoolAllocFunc alloc_func,
+ GstMemPoolFreeFunc free_func)
+{
+ GstMemPool *mem_pool;
+
+ g_return_val_if_fail (atom_size > 0, NULL);
+ g_return_val_if_fail (area_size >= atom_size, NULL);
+
+ mem_pool = g_malloc (sizeof (GstMemPool));
+
+ mem_pool->pool_size = atom_size + sizeof (GstMemPoolElement);
+ area_size = (area_size/atom_size) * mem_pool->pool_size;
+
+ mem_pool->name = g_strdup (name);
+ mem_pool->free = NULL;
+ mem_pool->cnt = 0;
+ mem_pool->atom_size = atom_size;
+ mem_pool->area_size = area_size;
+ mem_pool->cleanup = FALSE;
+ mem_pool->alloc_func = alloc_func;
+ mem_pool->free_func = free_func;
+ mem_pool->chunk_lock = g_mutex_new ();
+
+ populate (mem_pool);
+
+ return mem_pool;
+}
+
+static gboolean
+free_area (gpointer key, gpointer value, gpointer user_data)
+{
+ g_print ("free %p\n", key);
+ g_free (key);
+
+ return TRUE;
+}
+
+void
+gst_mem_pool_destroy (GstMemPool *mem_pool)
+{
+ GHashTable *elements = g_hash_table_new (NULL, NULL);
+ gpointer data;
+
+ mem_pool->cleanup = TRUE;
+
+ data = gst_mem_pool_alloc (mem_pool);
+ while (data) {
+ GstMemPoolElement *elem = GST_MEM_POOL_LINK (data);
+
+ g_hash_table_insert (elements, GST_MEM_POOL_AREA (elem), NULL);
+
+ data = gst_mem_pool_alloc (mem_pool);
+ }
+ g_hash_table_foreach_remove (elements, free_area, NULL);
+
+ g_hash_table_destroy (elements);
+ g_free (mem_pool->name);
+ g_free (mem_pool);
+}
+
+gpointer
+gst_mem_pool_alloc (GstMemPool *mem_pool)
+{
+ GstMemPoolElement *pool = NULL;
+
+ g_return_val_if_fail (mem_pool != NULL, NULL);
+
+again:
+#ifdef USE_ASM
+ __asm__ __volatile__ (" testl %%eax, %%eax \n\t"
+ " jz 20f \n"
+ "10: \t"
+ " movl (%%eax), %%ebx \n\t"
+ " movl %%edx, %%ecx \n\t"
+ " incl %%ecx \n\t"
+ POOL_LOCK "cmpxchg8b %1 \n\t"
+ " jz 20f \n\t"
+ " testl %%eax, %%eax \n\t"
+ " jnz 10b \n"
+ "20:\t"
+ :"=a" (pool)
+ :"m" (*mem_pool), "a" (mem_pool->free), "d" (mem_pool->cnt)
+ :"ecx", "ebx");
+#else
+ g_mutex_lock (mem_pool->chunk_lock);
+ if (mem_pool->free) {
+ pool = mem_pool->free;
+ mem_pool->free = pool->link;
+ }
+ g_mutex_unlock (mem_pool->chunk_lock);
+#endif
+
+ if (!pool) {
+ //g_print ("extending\n");
+ if (populate (mem_pool))
+ goto again;
+ else
+ return NULL;
+ }
+ return GST_MEM_POOL_DATA (pool);
+}
+
+gpointer
+gst_mem_pool_alloc0 (GstMemPool *mem_pool)
+{
+ gpointer mem = gst_mem_pool_alloc (mem_pool);
+
+ if (mem)
+ memset (mem, 0, mem_pool->atom_size);
+
+ return mem;
+}
+
+void
+gst_mem_pool_free (GstMemPool *mem_pool, gpointer mem)
+{
+ GstMemPoolElement *pool;
+
+ g_return_if_fail (mem_pool != NULL);
+ g_return_if_fail (mem != NULL);
+
+ pool = GST_MEM_POOL_LINK (mem);
+
+#ifdef USE_ASM
+ __asm__ __volatile__ ( "1: \t"
+ " movl %2, (%1) \n"
+ POOL_LOCK "cmpxchg %1, %0 \n\t"
+ " jnz 1b \n\t"
+ :
+ :"m" (*mem_pool), "r" (pool), "a" (mem_pool->free));
+#else
+ g_mutex_lock (mem_pool->chunk_lock);
+ pool->link = mem_pool->free;
+ mem_pool->free = pool;
+ g_mutex_unlock (mem_pool->chunk_lock);
+#endif
+}
diff --git a/test/bufspeed/gstmempool.h b/test/bufspeed/gstmempool.h
new file mode 100644
index 0000000000..307b768892
--- /dev/null
+++ b/test/bufspeed/gstmempool.h
@@ -0,0 +1,43 @@
+#include
+
+typedef struct _GstMemPool GstMemPool;
+typedef struct _GstMemPoolElement GstMemPoolElement;
+
+typedef void (*GstMemPoolAllocFunc) (GstMemPool *pool, gpointer data);
+typedef void (*GstMemPoolFreeFunc) (GstMemPool *pool, gpointer data);
+
+struct _GstMemPoolElement
+{
+ GstMemPoolElement *link; /* next cell in the lifo */
+ GstMemPoolElement *area;
+};
+
+struct _GstMemPool
+{
+ volatile GstMemPoolElement *free; /* the first free element */
+ volatile gulong cnt; /* used to avoid ABA problem */
+
+ gchar *name;
+ gulong area_size;
+ gulong pool_size;
+ gulong atom_size;
+ gboolean cleanup;
+ GstMemPoolAllocFunc alloc_func;
+ GstMemPoolFreeFunc free_func;
+ GMutex *chunk_lock;
+};
+
+
+GstMemPool* gst_mem_pool_new (gchar *name,
+ gint atom_size,
+ gulong area_size,
+ gint type,
+ GstMemPoolAllocFunc alloc_func,
+ GstMemPoolFreeFunc free_func);
+
+void gst_mem_pool_destroy (GstMemPool *mem_pool);
+
+gpointer gst_mem_pool_alloc (GstMemPool *mem_pool);
+gpointer gst_mem_pool_alloc0 (GstMemPool *mem_pool);
+void gst_mem_pool_free (GstMemPool *mem_pool,
+ gpointer mem);
diff --git a/test/bufspeed/test1.c b/test/bufspeed/test1.c
new file mode 100644
index 0000000000..951af46067
--- /dev/null
+++ b/test/bufspeed/test1.c
@@ -0,0 +1,19 @@
+#include "gstbuffer.h"
+
+int
+main (int argc, char *argv[])
+{
+ GstBuffer *buf;
+ guint i;
+
+ g_thread_init (NULL);
+ gtk_init (&argc, &argv);
+ _gst_buffer_initialize ();
+
+ for (i=0; i<5000000; i++) {
+ buf = gst_buffer_new ();
+ gst_buffer_unref (buf);
+ }
+
+ return 0;
+}
diff --git a/test/bufspeed/test2.c b/test/bufspeed/test2.c
new file mode 100644
index 0000000000..616ad1f554
--- /dev/null
+++ b/test/bufspeed/test2.c
@@ -0,0 +1,19 @@
+#include
+
+int
+main (int argc, char *argv[])
+{
+ GstBuffer *buf;
+ guint i;
+
+ g_thread_init (NULL);
+ gtk_init (&argc, &argv);
+ _gst_buffer_initialize ();
+
+ for (i=0; i<5000000; i++) {
+ buf = gst_buffer_new ();
+ gst_buffer_unref (buf);
+ }
+
+ return 0;
+}
diff --git a/test/dvshow.c b/test/dvshow.c
index 833e3feabd..d82c4d0f2a 100644
--- a/test/dvshow.c
+++ b/test/dvshow.c
@@ -86,7 +86,9 @@ main (int argc,char *argv[])
gtk_widget_show_all(appwindow);
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("dvshow.xml",gst_xml_write(GST_ELEMENT(bin)));
+#endif
gst_element_set_state(GST_ELEMENT(bin),GST_STATE_PLAYING);
diff --git a/test/events/Makefile.am b/test/events/Makefile.am
new file mode 100644
index 0000000000..f2300be1ac
--- /dev/null
+++ b/test/events/Makefile.am
@@ -0,0 +1,4 @@
+noinst_PROGRAMS = seek
+
+LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
diff --git a/test/events/seek.c b/test/events/seek.c
new file mode 100644
index 0000000000..89a6e27189
--- /dev/null
+++ b/test/events/seek.c
@@ -0,0 +1,68 @@
+#include
+
+int
+main (int argc, char *argv[])
+{
+ GstBin *bin;
+ GstElement *src, *sink;
+ GstPad *srcpad, *sinkpad;
+
+// _gst_plugin_spew = TRUE;
+ gst_init (&argc, &argv);
+
+ bin = GST_BIN (gst_pipeline_new ("pipeline"));
+ g_return_val_if_fail (bin != NULL, -1);
+
+ g_print ("--- creating src and sink elements\n");
+ src = gst_elementfactory_make ("fakesrc", "src");
+ g_return_val_if_fail (src != NULL, -1);
+ sink = gst_elementfactory_make ("fakesink", "sink");
+ g_return_val_if_fail (sink != NULL, -1);
+
+ g_print ("--- about to add the elements to the bin\n");
+ gst_bin_add (bin, GST_ELEMENT (src));
+ gst_bin_add (bin, GST_ELEMENT (sink));
+
+ g_print ("--- getting pads\n");
+ srcpad = gst_element_get_pad (src, "src");
+ g_return_val_if_fail (srcpad != NULL, -1);
+ sinkpad = gst_element_get_pad (sink, "sink");
+ g_return_val_if_fail (srcpad != NULL, -1);
+
+ g_print ("--- connecting\n");
+ gst_pad_connect (srcpad, sinkpad);
+
+ g_print ("--- setting up\n");
+ gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
+
+ g_print ("--- iterating\n");
+ gst_bin_iterate (bin);
+ gst_bin_iterate (bin);
+
+ g_print ("--- seek to 100\n");
+ gst_pad_send_event (srcpad, gst_event_new_seek (GST_SEEK_ANY, 100, FALSE));
+
+ g_print ("--- seek done, iterating\n");
+ gst_bin_iterate (bin);
+ gst_bin_iterate (bin);
+
+ g_print ("--- seek to 200 with flush\n");
+ gst_pad_send_event (srcpad, gst_event_new_seek (GST_SEEK_ANY, 200, TRUE));
+
+ g_print ("--- seek done, iterating\n");
+ gst_bin_iterate (bin);
+ gst_bin_iterate (bin);
+ gst_bin_iterate (bin);
+
+ g_print ("--- flush\n");
+ gst_pad_send_event (srcpad, gst_event_new_flush ());
+
+ g_print ("--- flush done, iterating\n");
+ gst_bin_iterate (bin);
+ gst_bin_iterate (bin);
+
+ g_print ("--- cleaning up\n");
+ gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
+
+ return 0;
+}
diff --git a/test/main.c b/test/main.c
index 35f23d0016..5c71c6f4d7 100644
--- a/test/main.c
+++ b/test/main.c
@@ -140,7 +140,9 @@ gst_play_have_type (GstElement *typefind, GstCaps *caps, GstPlayInfo *info)
gst_element_set_state (pipeline, GST_STATE_PLAYING);
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("xmlTest.gst", gst_xml_write (GST_ELEMENT (pipeline)));
+#endif
}
diff --git a/test/memchunk/Makefile.am b/test/memchunk/Makefile.am
new file mode 100644
index 0000000000..e3198c289e
--- /dev/null
+++ b/test/memchunk/Makefile.am
@@ -0,0 +1,7 @@
+noinst_PROGRAMS = gmemchunktest gstmemchunktest
+
+gmemchunktest_SOURCES = gmemchunktest.c
+gstmemchunktest_SOURCES = gstmemchunktest.c gstmemchunk.c gstmemchunk.h
+
+LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
diff --git a/test/memchunk/gmemchunktest.c b/test/memchunk/gmemchunktest.c
new file mode 100644
index 0000000000..b3301f13dd
--- /dev/null
+++ b/test/memchunk/gmemchunktest.c
@@ -0,0 +1,78 @@
+#include
+
+#define MAX_THREADS 100
+
+static GMemChunk *_chunks;
+static GMutex *_lock;
+
+static gint num_allocs;
+static gint num_threads;
+
+static gpointer
+alloc_chunk (void)
+{
+ gpointer ret;
+ g_mutex_lock (_lock);
+ ret = g_mem_chunk_alloc (_chunks);
+ g_mutex_unlock (_lock);
+
+ return ret;
+}
+
+static void
+free_chunk (gpointer chunk)
+{
+ g_mutex_lock (_lock);
+ g_mem_chunk_free (_chunks, chunk);
+ g_mutex_unlock (_lock);
+}
+
+
+void*
+run_test (void *threadid)
+{
+ gint i;
+ gpointer chunk;
+ sleep(1);
+
+ for (i = 0; i \n", argv[0]);
+ exit (-1);
+ }
+
+ num_threads = atoi (argv[1]);
+ num_allocs = atoi (argv[2]);
+
+ _chunks = g_mem_chunk_new ("test", 32, 32 * 16, G_ALLOC_AND_FREE);
+ _lock = g_mutex_new ();
+
+ for(t=0; t < num_threads; t++) {
+ rc = pthread_create (&threads[t], NULL, run_test, (void *)t);
+ if (rc) {
+ printf ("ERROR: return code from pthread_create() is %d\n", rc);
+ printf ("Code %d= %s\n", rc, strerror(rc));
+ exit (-1);
+ }
+ }
+ printf ("main(): Created %d threads.\n", t);
+
+ pthread_exit (NULL);
+ g_mem_chunk_info();
+}
diff --git a/test/memchunk/gstmemchunk.c b/test/memchunk/gstmemchunk.c
new file mode 100644
index 0000000000..be99be5a79
--- /dev/null
+++ b/test/memchunk/gstmemchunk.c
@@ -0,0 +1,162 @@
+#include "gstmemchunk.h"
+
+#ifdef __SMP__
+#define CHUNK_LOCK "lock ; "
+#else
+#define CHUNK_LOCK ""
+#endif
+
+#define GST_MEM_CHUNK_AREA(chunk) (((GstMemChunkElement*)(chunk))->area)
+#define GST_MEM_CHUNK_DATA(chunk) ((gpointer)(((GstMemChunkElement*)(chunk)) + 1))
+#define GST_MEM_CHUNK_LINK(mem) ((GstMemChunkElement*)((guint8*)(mem) - sizeof (GstMemChunkElement)))
+
+/*******************************************************
+ * area size
+ * +-----------------------------------------+
+ * chunk size
+ * +------------+
+ *
+ * !next!data... !next!data.... !next!data...
+ * ! ^ ! ^ !
+ * +-------------+ +------------+ +---> NULL
+ *
+ */
+static gboolean
+populate (GstMemChunk *mem_chunk)
+{
+ guint8 *area;
+ gint i;
+
+ if (mem_chunk->cleanup)
+ return FALSE;
+
+ area = (guint8 *) g_malloc (mem_chunk->area_size);
+ g_print ("alloc %p\n", area);
+
+ for (i=0; i < mem_chunk->area_size; i += mem_chunk->chunk_size) {
+ GST_MEM_CHUNK_AREA (area + i) = (GstMemChunkElement *)area;
+ gst_mem_chunk_free (mem_chunk, GST_MEM_CHUNK_DATA (area + i));
+ }
+
+ return TRUE;
+}
+
+
+GstMemChunk*
+gst_mem_chunk_new (gchar* name, gint atom_size, gulong area_size, gint type)
+{
+ GstMemChunk *mem_chunk;
+
+ g_return_val_if_fail (atom_size > 0, NULL);
+ g_return_val_if_fail (area_size >= atom_size, NULL);
+
+ mem_chunk = g_malloc (sizeof (GstMemChunk));
+
+ mem_chunk->chunk_size = atom_size + sizeof (GstMemChunkElement);
+ area_size = (area_size/atom_size) * mem_chunk->chunk_size;
+
+ mem_chunk->name = g_strdup (name);
+ mem_chunk->free = NULL;
+ mem_chunk->cnt = 0;
+ mem_chunk->atom_size = atom_size;
+ mem_chunk->area_size = area_size;
+ mem_chunk->cleanup = FALSE;
+
+ populate (mem_chunk);
+
+ return mem_chunk;
+}
+
+static gboolean
+free_area (gpointer key, gpointer value, gpointer user_data)
+{
+ g_print ("free %p\n", key);
+ g_free (key);
+
+ return TRUE;
+}
+
+void
+gst_mem_chunk_destroy (GstMemChunk *mem_chunk)
+{
+ GHashTable *elements = g_hash_table_new (NULL, NULL);
+ gpointer data;
+
+ mem_chunk->cleanup = TRUE;
+
+ data = gst_mem_chunk_alloc (mem_chunk);
+ while (data) {
+ GstMemChunkElement *elem = GST_MEM_CHUNK_LINK (data);
+
+ g_hash_table_insert (elements, GST_MEM_CHUNK_AREA (elem), NULL);
+
+ data = gst_mem_chunk_alloc (mem_chunk);
+ }
+ g_hash_table_foreach_remove (elements, free_area, NULL);
+
+ g_hash_table_destroy (elements);
+ g_free (mem_chunk->name);
+ g_free (mem_chunk);
+}
+
+gpointer
+gst_mem_chunk_alloc (GstMemChunk *mem_chunk)
+{
+ GstMemChunkElement *chunk = NULL;
+
+ g_return_val_if_fail (mem_chunk != NULL, NULL);
+
+again:
+ __asm__ __volatile__ (" testl %%eax, %%eax \n\t"
+ " jz 20f \n"
+ "10: \t"
+ " movl (%%eax), %%ebx \n\t"
+ " movl %%edx, %%ecx \n\t"
+ " incl %%ecx \n\t"
+ CHUNK_LOCK "cmpxchg8b %1 \n\t"
+ " jz 20f \n\t"
+ " testl %%eax, %%eax \n\t"
+ " jnz 10b \n"
+ "20:\t"
+ :"=a" (chunk)
+ :"m" (*mem_chunk), "a" (mem_chunk->free), "d" (mem_chunk->cnt)
+ :"ecx", "ebx");
+
+ if (!chunk) {
+ //g_print ("extending\n");
+ if (populate (mem_chunk))
+ goto again;
+ else
+ return NULL;
+ }
+ return GST_MEM_CHUNK_DATA (chunk);
+}
+
+gpointer
+gst_mem_chunk_alloc0 (GstMemChunk *mem_chunk)
+{
+ gpointer mem = gst_mem_chunk_alloc (mem_chunk);
+
+ if (mem)
+ memset (mem, 0, mem_chunk->atom_size);
+
+ return mem;
+}
+
+void
+gst_mem_chunk_free (GstMemChunk *mem_chunk, gpointer mem)
+{
+ GstMemChunkElement *chunk;
+
+ g_return_if_fail (mem_chunk != NULL);
+ g_return_if_fail (mem != NULL);
+
+ chunk = GST_MEM_CHUNK_LINK (mem);
+
+ __asm__ __volatile__ ( "1: \t"
+ " movl %2, (%1) \n"
+ CHUNK_LOCK "cmpxchg %1, %0 \n\t"
+ " jnz 1b \n\t"
+ :
+ :"m" (*mem_chunk), "r" (chunk), "a" (mem_chunk->free));
+}
diff --git a/test/memchunk/gstmemchunk.h b/test/memchunk/gstmemchunk.h
new file mode 100644
index 0000000000..c71660a567
--- /dev/null
+++ b/test/memchunk/gstmemchunk.h
@@ -0,0 +1,34 @@
+
+#include
+
+typedef struct _GstMemChunk GstMemChunk;
+typedef struct _GstMemChunkElement GstMemChunkElement;
+
+struct _GstMemChunkElement
+{
+ GstMemChunkElement *link; /* next cell in the lifo */
+ GstMemChunkElement *area;
+};
+
+struct _GstMemChunk
+{
+ volatile GstMemChunkElement *free; /* the first free element */
+ volatile gulong cnt; /* used to avoid ABA problem */
+
+ gchar *name;
+ gulong area_size;
+ gulong chunk_size;
+ gulong atom_size;
+ gboolean cleanup;
+};
+
+GstMemChunk* gst_mem_chunk_new (gchar *name,
+ gint atom_size,
+ gulong area_size,
+ gint type);
+
+void gst_mem_chunk_destroy (GstMemChunk *mem_chunk);
+
+gpointer gst_mem_chunk_alloc (GstMemChunk *mem_chunk);
+void gst_mem_chunk_free (GstMemChunk *mem_chunk,
+ gpointer mem);
diff --git a/test/memchunk/gstmemchunktest.c b/test/memchunk/gstmemchunktest.c
new file mode 100644
index 0000000000..05acccb104
--- /dev/null
+++ b/test/memchunk/gstmemchunktest.c
@@ -0,0 +1,79 @@
+#include
+#include "gstmemchunk.h"
+
+#define MAX_THREADS 100
+
+static GstMemChunk *_chunks;
+
+static gint num_allocs;
+static gint num_threads;
+
+static gpointer
+alloc_chunk (void)
+{
+ gpointer ret;
+ ret = gst_mem_chunk_alloc (_chunks);
+
+ return ret;
+}
+
+static void
+free_chunk (gpointer chunk)
+{
+ gst_mem_chunk_free (_chunks, chunk);
+}
+
+
+void*
+run_test (void *threadid)
+{
+ gint i;
+ gpointer chunk;
+ sleep(1);
+
+ for (i = 0; i \n", argv[0]);
+ exit (-1);
+ }
+
+ num_threads = atoi (argv[1]);
+ num_allocs = atoi (argv[2]);
+
+ _chunks = gst_mem_chunk_new ("test", 32, 32 * 16, G_ALLOC_AND_FREE);
+
+ for(t=0; t < num_threads; t++) {
+ rc = pthread_create (&threads[t], NULL, run_test, (void *)t);
+ if (rc) {
+ printf ("ERROR: return code from pthread_create() is %d\n", rc);
+ printf ("Code %d= %s\n", rc, strerror(rc));
+ exit (-1);
+ }
+ }
+ printf ("main(): Created %d threads.\n", t);
+
+ for(t=0; t < num_threads; t++) {
+ pthread_join (threads[t], NULL);
+ }
+ g_mem_chunk_info();
+
+ gst_mem_chunk_destroy (_chunks);
+
+ return 0;
+}
diff --git a/test/mpeg2parse2.c b/test/mpeg2parse2.c
index 75a04c42f2..29f2d98d39 100644
--- a/test/mpeg2parse2.c
+++ b/test/mpeg2parse2.c
@@ -16,7 +16,7 @@ gboolean idle_func(gpointer data) {
void mpeg2parse_newpad(GstElement *parser,GstPad *pad, GstElement *pipeline) {
- g_print("***** a new pad %s was created\n", gst_pad_get_name(pad));
+ g_print("***** a new pad %s was created %p\n", gst_pad_get_name(pad), pipeline);
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED);
if (strncmp(gst_pad_get_name(pad), "video_", 6) == 0) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 257a9ed1c6..43ac3402a0 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,8 +1,15 @@
SUBDIRS = sched eos nego muxing
-noinst_PROGRAMS = init loadall simplefake states caps queue registry \
-paranoia rip mp3encode autoplug props case4 markup load tee autoplug2 autoplug3 \
-capsconnect padfactory autoplug4 incsched reaping threadlock mp1vid reconnect \
+if GST_DISABLE_LOADSAVE
+GST_LOADSAVE_PROG =
+else
+GST_LOADSAVE_PROG = caps registry autoplug props tee autoplug2 capsconnect \
+ padfactory autoplug4
+endif
+
+noinst_PROGRAMS = $(GST_LOADSAVE_PROG) init loadall simplefake states queue \
+paranoia rip mp3encode case4 markup load autoplug3 \
+incsched reaping threadlock mp1vid reconnect \
faketest events timecache
# we have nothing but apps here, we can do this safely
diff --git a/tests/old/examples/Makefile.am b/tests/old/examples/Makefile.am
index 6fe9c9c70b..b81c1568f7 100644
--- a/tests/old/examples/Makefile.am
+++ b/tests/old/examples/Makefile.am
@@ -5,10 +5,16 @@ else
GNOME_SUBDS =
endif
-SUBDIRS = $(GNOME_SUBDS) \
+if GST_DISABLE_LOADSAVE
+GST_LOADSAVE_DIRS =
+else
+GST_LOADSAVE_DIRS = xml typefind
+endif
+
+SUBDIRS = $(GNOME_SUBDS) $(GST_LOADSAVE_DIRS) \
helloworld helloworld2 \
queue queue2 queue3 queue4 \
- launch thread xml plugins typefind mixer cutter
+ launch thread plugins mixer cutter
DIST_SUBDIRS = autoplug \
helloworld helloworld2 \
diff --git a/tests/old/examples/autoplug/autoplug.c b/tests/old/examples/autoplug/autoplug.c
index 550b182530..9de5ba56f2 100644
--- a/tests/old/examples/autoplug/autoplug.c
+++ b/tests/old/examples/autoplug/autoplug.c
@@ -94,7 +94,9 @@ gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline)
gst_element_set_state (pipeline, GST_STATE_PLAYING);
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("xmlTest.gst", gst_xml_write (GST_ELEMENT (pipeline)));
+#endif
}
gboolean
diff --git a/tests/old/examples/mixer/mixer.c b/tests/old/examples/mixer/mixer.c
index 0edbfa539f..7a02eddcb4 100644
--- a/tests/old/examples/mixer/mixer.c
+++ b/tests/old/examples/mixer/mixer.c
@@ -182,7 +182,9 @@ int main(int argc,char *argv[])
}
env_register_cp (channel_in->volenv, num_channels * 10.0 , 1.0 / num_channels); /* to end level */
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("mixer.xml", gst_xml_write(GST_ELEMENT(main_bin)));
+#endif
/* start playing */
gst_element_set_state(main_bin, GST_STATE_PLAYING);
@@ -356,7 +358,9 @@ create_input_channel (int id, char* location)
gst_element_get_pad (decoder, "src"), "src_00");
#endif
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile ("mixer.gst", gst_xml_write (new_element));
+#endif
gst_bin_add (GST_BIN(channel->pipe), channel->volenv);
gst_bin_add (GST_BIN (channel->pipe), new_element);
diff --git a/tests/old/testsuite/bytestream/.gitignore b/tests/old/testsuite/bytestream/.gitignore
new file mode 100644
index 0000000000..7df60c92d6
--- /dev/null
+++ b/tests/old/testsuite/bytestream/.gitignore
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+test1
diff --git a/tests/old/testsuite/bytestream/Makefile.am b/tests/old/testsuite/bytestream/Makefile.am
new file mode 100644
index 0000000000..75aeed7915
--- /dev/null
+++ b/tests/old/testsuite/bytestream/Makefile.am
@@ -0,0 +1,13 @@
+filterdir = $(libdir)/gst
+
+testprogs = test1
+
+check_PROGRAMS = $(testprogs)
+
+test1_SOURCES = test1.c gstbstest.c mem.c
+test1_LDFLAGS = -L$(top_builddir)/libs/bytestream/ -lgstbytestream
+
+
+# we have nothing but apps here, we can do this safely
+LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
diff --git a/tests/old/testsuite/bytestream/gstbstest.c b/tests/old/testsuite/bytestream/gstbstest.c
new file mode 100644
index 0000000000..4199a905f6
--- /dev/null
+++ b/tests/old/testsuite/bytestream/gstbstest.c
@@ -0,0 +1,407 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstbstest.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include
+#include
+
+#include
+#include
+
+#define GST_TYPE_BSTEST (gst_bstest_get_type())
+#define GST_BSTEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BSTEST,GstBsTest))
+#define GST_BSTEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BSTEST,GstBsTestClass))
+#define GST_IS_BSTEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BSTEST))
+#define GST_IS_BSTEST_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BSTEST))
+
+typedef struct _GstBsTest GstBsTest;
+typedef struct _GstBsTestClass GstBsTestClass;
+
+struct _GstBsTest
+{
+ GstElement element;
+
+ GstPad *sinkpad;
+ GstPad *srcpad;
+
+ GstByteStream *bs;
+
+ gchar *accesspattern;
+ guint num_patterns;
+ gchar **patterns;
+ guint sizemin;
+ guint sizemax;
+ gint count;
+ gboolean silent;
+};
+
+struct _GstBsTestClass
+{
+ GstElementClass parent_class;
+};
+
+GType gst_bstest_get_type (void);
+
+
+GstElementDetails gst_bstest_details = {
+ "ByteStreamTest",
+ "Filter",
+ "Test for the GstByteStream code",
+ VERSION,
+ "Erik Walthinsen ," "Wim Taymans ",
+ "(C) 2001",
+};
+
+
+/* BsTest signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ ARG_0,
+ ARG_SIZEMIN,
+ ARG_SIZEMAX,
+ ARG_COUNT,
+ ARG_SILENT,
+ ARG_ACCESSPATTERN,
+};
+
+
+static void gst_bstest_class_init (GstBsTestClass * klass);
+static void gst_bstest_init (GstBsTest * bstest);
+
+static void gst_bstest_set_property (GObject * object, guint prop_id, const GValue * value,
+ GParamSpec * pspec);
+static void gst_bstest_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec);
+
+static GstElementStateReturn gst_bstest_change_state (GstElement *element);
+static void gst_bstest_loop (GstElement * element);
+
+static GstElementClass *parent_class = NULL;
+
+// static guint gst_bstest_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_bstest_get_type (void)
+{
+ static GType bstest_type = 0;
+
+ if (!bstest_type) {
+ static const GTypeInfo bstest_info = {
+ sizeof (GstBsTestClass), NULL,
+ NULL,
+ (GClassInitFunc) gst_bstest_class_init,
+ NULL,
+ NULL,
+ sizeof (GstBsTest),
+ 0,
+ (GInstanceInitFunc) gst_bstest_init,
+ };
+
+ bstest_type = g_type_register_static (GST_TYPE_ELEMENT, "BSTest", &bstest_info, 0);
+ }
+ return bstest_type;
+}
+
+static void
+gst_bstest_class_init (GstBsTestClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass*)klass;
+
+ parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
+ g_param_spec_int ("sizemin", "sizemin", "sizemin", 0, G_MAXINT,
+ 0, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
+ g_param_spec_int ("sizemax", "sizemax", "sizemax", 0, G_MAXINT,
+ 384, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ACCESSPATTERN,
+ g_param_spec_string ("accesspattern", "accesspattern", "accesspattern",
+ "r", G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COUNT,
+ g_param_spec_uint ("count", "count", "count",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
+ g_param_spec_boolean ("silent", "silent", "silent",
+ FALSE, G_PARAM_READWRITE));
+
+ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bstest_set_property);
+ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bstest_get_property);
+
+ gstelement_class->change_state = gst_bstest_change_state;
+
+}
+
+static GstPadNegotiateReturn
+gst_bstest_negotiate_src (GstPad * pad, GstCaps ** caps, gpointer * data)
+{
+ GstBsTest *bstest;
+
+ bstest = GST_BSTEST (gst_pad_get_parent (pad));
+
+ return gst_pad_negotiate_proxy (pad, bstest->sinkpad, caps);
+}
+
+static GstPadNegotiateReturn
+gst_bstest_negotiate_sink (GstPad * pad, GstCaps ** caps, gpointer * data)
+{
+ GstBsTest *bstest;
+
+ bstest = GST_BSTEST (gst_pad_get_parent (pad));
+
+ return gst_pad_negotiate_proxy (pad, bstest->srcpad, caps);
+}
+
+static void
+gst_bstest_init (GstBsTest * bstest)
+{
+ bstest->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+ gst_element_add_pad (GST_ELEMENT (bstest), bstest->sinkpad);
+ gst_pad_set_negotiate_function (bstest->sinkpad, gst_bstest_negotiate_sink);
+
+ bstest->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+ gst_element_add_pad (GST_ELEMENT (bstest), bstest->srcpad);
+ gst_pad_set_negotiate_function (bstest->srcpad, gst_bstest_negotiate_src);
+
+ gst_element_set_loop_function (GST_ELEMENT (bstest), gst_bstest_loop);
+
+ bstest->sizemin = 0;
+ bstest->sizemax = 384;
+ bstest->accesspattern = g_strdup ("r");
+ bstest->patterns = g_strsplit (bstest->accesspattern, ":", 0);
+ bstest->count = 5;
+ bstest->silent = FALSE;
+ bstest->bs = NULL;
+}
+
+static guint
+gst_bstest_get_size (GstBsTest *bstest, gchar *sizestring, guint prevsize)
+{
+ guint size;
+
+ if (sizestring[0] == 0) {
+ size = bstest->sizemax;
+ }
+ else if (sizestring[0] == 'r') {
+ size = bstest->sizemin + (guint8)(((gfloat)bstest->sizemax)*rand()/(RAND_MAX + (gfloat)bstest->sizemin));
+ }
+ else if (sizestring[0] == '<') {
+ size = prevsize;
+ }
+ else {
+ size = atoi (sizestring);
+ }
+
+ if (size == 0) size++;
+
+ return size;
+}
+
+static void
+gst_bstest_loop (GstElement * element)
+{
+ GstBsTest *bstest;
+ GstBuffer *buf = NULL;
+
+ g_return_if_fail (element != NULL);
+ g_return_if_fail (GST_IS_BSTEST (element));
+
+ bstest = GST_BSTEST (element);
+
+ do {
+ guint size = 0;
+ guint i = 0;
+
+ while (i < bstest->num_patterns) {
+ buf = NULL;
+
+ if (bstest->patterns[i][0] == 'r') {
+ size = gst_bstest_get_size (bstest, &bstest->patterns[i][1], size);
+ if (!bstest->silent) g_print ("bstest: ***** read %d bytes\n", size);
+ buf = gst_bytestream_read (bstest->bs, size);
+ }
+ else if (bstest->patterns[i][0] == 'f') {
+ size = gst_bstest_get_size (bstest, &bstest->patterns[i][1], size);
+ if (!bstest->silent) g_print ("bstest: ***** flush %d bytes\n", size);
+ gst_bytestream_flush (bstest->bs, size);
+ }
+ else if (!strncmp (bstest->patterns[i], "pb", 2)) {
+ size = gst_bstest_get_size (bstest, &bstest->patterns[i][2], size);
+ if (!bstest->silent) g_print ("bstest: ***** peek bytes %d bytes\n", size);
+ gst_bytestream_peek_bytes (bstest->bs, size);
+ }
+ else if (bstest->patterns[i][0] == 'p') {
+ size = gst_bstest_get_size (bstest, &bstest->patterns[i][1], size);
+ if (!bstest->silent) g_print ("bstest: ***** peek %d bytes\n", size);
+ buf = gst_bytestream_peek (bstest->bs, size);
+ gst_buffer_unref (buf);
+ buf = NULL;
+ }
+
+ if (buf)
+ gst_pad_push (bstest->srcpad, buf);
+
+ i++;
+ }
+ } while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
+}
+
+static void
+gst_bstest_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstBsTest *bstest;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (GST_IS_BSTEST (object));
+
+ bstest = GST_BSTEST (object);
+
+ switch (prop_id) {
+ case ARG_SIZEMIN:
+ bstest->sizemin = g_value_get_int (value);
+ break;
+ case ARG_SIZEMAX:
+ bstest->sizemax = g_value_get_int (value);
+ break;
+ case ARG_ACCESSPATTERN:
+ if (bstest->accesspattern) {
+ g_free (bstest->accesspattern);
+ g_strfreev (bstest->patterns);
+ }
+ if (g_value_get_string (value) == NULL) {
+ gst_element_set_state (GST_ELEMENT (object), GST_STATE_NULL);
+ bstest->accesspattern = NULL;
+ bstest->num_patterns = 0;
+ } else {
+ guint i = 0;
+
+ bstest->accesspattern = g_strdup (g_value_get_string (value));
+ bstest->patterns = g_strsplit (bstest->accesspattern, ":", 0);
+ while (bstest->patterns[i++]);
+ bstest->num_patterns = i-1;
+ }
+ break;
+ case ARG_COUNT:
+ bstest->count = g_value_get_uint (value);
+ break;
+ case ARG_SILENT:
+ bstest->silent = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_bstest_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstBsTest *bstest;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (GST_IS_BSTEST (object));
+
+ bstest = GST_BSTEST (object);
+
+ switch (prop_id) {
+ case ARG_SIZEMIN:
+ g_value_set_int (value, bstest->sizemin);
+ break;
+ case ARG_SIZEMAX:
+ g_value_set_int (value, bstest->sizemax);
+ break;
+ case ARG_ACCESSPATTERN:
+ g_value_set_string (value, bstest->accesspattern);
+ break;
+ case ARG_COUNT:
+ g_value_set_uint (value, bstest->count);
+ break;
+ case ARG_SILENT:
+ g_value_set_boolean (value, bstest->silent);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstElementStateReturn
+gst_bstest_change_state (GstElement *element)
+{
+ GstBsTest *bstest;
+
+ g_return_val_if_fail (GST_IS_BSTEST (element), GST_STATE_FAILURE);
+
+ bstest = GST_BSTEST (element);
+
+ if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
+ if (bstest->bs) {
+ gst_bytestream_destroy (bstest->bs);
+ bstest->bs = NULL;
+ }
+ }
+ else {
+ if (!bstest->bs) {
+ bstest->bs = gst_bytestream_new (bstest->sinkpad);
+ }
+ }
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+ return GST_STATE_SUCCESS;
+}
+
+static gboolean
+plugin_init (GModule * module, GstPlugin * plugin)
+{
+ GstElementFactory *factory;
+
+ // we need gstbytestream
+ if (!gst_library_load ("gstbytestream")) {
+ g_print ("can't load bytestream\n");
+ return FALSE;
+ }
+
+ /* We need to create an ElementFactory for each element we provide.
+ * This consists of the name of the element, the GType identifier,
+ * and a pointer to the details structure at the top of the file.
+ */
+ factory = gst_elementfactory_new ("bstest", GST_TYPE_BSTEST, &gst_bstest_details);
+ g_return_val_if_fail (factory != NULL, FALSE);
+
+ /* The very last thing is to register the elementfactory with the plugin. */
+ gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+ return TRUE;
+}
+
+GST_PLUGIN_DESC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "bstest", plugin_init);
diff --git a/tests/old/testsuite/bytestream/mem.c b/tests/old/testsuite/bytestream/mem.c
new file mode 100644
index 0000000000..d1c36cb5aa
--- /dev/null
+++ b/tests/old/testsuite/bytestream/mem.c
@@ -0,0 +1,23 @@
+#include
+#include
+#include
+#include
+#include
+
+int vmsize() {
+ int pid,fd,size,i,mem;
+ char filename[17], buf[256], *ptr, *end;
+
+ pid = getpid();
+ snprintf(filename,17,"/proc/%d/stat",pid);
+ fd = open(filename,O_RDONLY);
+ size = read(fd,buf,240);
+ ptr = buf;
+ for (i=0;i<22;i++)
+ ptr = (char *)strchr(ptr,' ') + 1;
+ end = (char *)strchr(ptr,' ');
+ *end = 0;
+ sscanf(ptr,"%d",&mem);
+ close(fd);
+ return mem;
+}
diff --git a/tests/old/testsuite/bytestream/mem.h b/tests/old/testsuite/bytestream/mem.h
new file mode 100644
index 0000000000..28999db2c3
--- /dev/null
+++ b/tests/old/testsuite/bytestream/mem.h
@@ -0,0 +1 @@
+int vmsize();
diff --git a/tests/old/testsuite/bytestream/test1.c b/tests/old/testsuite/bytestream/test1.c
new file mode 100644
index 0000000000..0670849e84
--- /dev/null
+++ b/tests/old/testsuite/bytestream/test1.c
@@ -0,0 +1,230 @@
+#include
+#include
+
+#include
+#include "mem.h"
+
+#define VM_THRES 1000
+#define MAX_CONFIG_LINE 255
+#define MAX_CONFIG_PATTERN 64
+
+typedef struct
+{
+ gint src_data;
+ gint src_sizetype;
+
+ gchar *bs_accesspattern;
+
+ gboolean integrity_check;
+} TestParam;
+
+static GSList *params = NULL;
+
+static guint8 count;
+static guint iterations;
+static gboolean integrity_check = TRUE;
+static gboolean verbose = FALSE;
+static gboolean dump = FALSE;
+
+static void
+handoff (GstElement *element, GstBuffer *buf, GstPad *pad, gpointer data)
+{
+ if (GST_IS_BUFFER (buf)) {
+ if (integrity_check) {
+ gint i;
+ guint8 *ptr = GST_BUFFER_DATA (buf);
+
+ for (i=0; isrc_sizetype == 2 ? "fixed" : "random"),
+ (param->src_data == 1 ? "src" : "subbuffer"),
+ param->bs_accesspattern);
+ return desc;
+}
+
+static gboolean
+read_param_file (gchar *filename)
+{
+ FILE *fp;
+ gchar line[MAX_CONFIG_LINE+1];
+ guint linenr = 0;
+ gchar pattern[MAX_CONFIG_PATTERN];
+ gint data, sizetype, integrity_check;
+ gchar *scan_str;
+ gboolean res = TRUE;
+
+ fp = fopen (filename, "r");
+ if (fp == NULL)
+ return FALSE;
+
+ scan_str = g_strdup_printf ("%%d %%d %%%ds %%d", MAX_CONFIG_PATTERN-1);
+
+ while (fgets (line, MAX_CONFIG_LINE, fp)) {
+ linenr++;
+
+ if (line[0] == '\n' || line[0] == '#')
+ continue;
+
+ if (sscanf (line, scan_str, &data, &sizetype, pattern, &integrity_check) != 4) {
+ g_print ("error on line: %d\n", linenr);
+ res = FALSE;
+ break;
+ }
+ else {
+ TestParam *param = g_malloc (sizeof (TestParam));
+
+ param->src_data = data;
+ param->src_sizetype = sizetype;
+ param->bs_accesspattern = g_strdup (pattern);
+ param->integrity_check = (integrity_check == 0 ? FALSE : TRUE);
+
+ params = g_slist_append (params, param);
+ }
+ }
+ g_free (scan_str);
+
+ return res;
+}
+
+static void
+run_test (GstBin *pipeline, gint iters)
+{
+ gint vm = 0;
+ gint maxiters = iters;
+ gint prev_percent = -1;
+
+ count = 0;
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+
+ while (iters) {
+ gint newvm = vmsize();
+ gint percent;
+
+ percent = (gint)((maxiters-iters+1)*100.0/maxiters);
+
+ if (percent != prev_percent || newvm - vm > VM_THRES) {
+ g_print ("\r%d (delta %d) %.3d%% ", newvm, newvm - vm, percent);
+ prev_percent = percent;
+ vm = newvm;
+ }
+ gst_bin_iterate (pipeline);
+
+ if (iters > 0) iters--;
+ }
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+}
+
+static void
+usage (char *argv[])
+{
+ g_print ("usage: %s [--verbose] [--dump] \n", argv[0]);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GstElement *src;
+ GstElement *sink;
+ GstElement *bs;
+ GstElement *pipeline;
+ gint testnum = 0;
+ GSList *walk;
+ gint arg_walk;
+
+ gst_init (&argc, &argv);
+
+ arg_walk = 1;
+ while ((arg_walk < argc) && (argv[arg_walk][0] == '-')) {
+ if (!strncmp (argv[arg_walk], "--verbose", 9))
+ verbose = TRUE;
+ else if (!strncmp (argv[arg_walk], "--dump", 6))
+ dump = TRUE;
+ else {
+ g_print ("unknown option %s (ignored)\n", argv[arg_walk]);
+ }
+
+ arg_walk++;
+ }
+ if (argc - arg_walk < 2) {
+ usage(argv);
+ return -1;
+ }
+ if (!read_param_file (argv[arg_walk])) {
+ g_print ("error reading file %s\n", argv[arg_walk]);
+ usage (argv);
+ return -1;
+ }
+ arg_walk++;
+ iterations = atoi (argv[arg_walk]);
+
+ pipeline = gst_elementfactory_make ("pipeline", "pipeline");
+ g_assert (pipeline);
+
+ src = gst_elementfactory_make ("fakesrc", "src");
+ g_assert (src);
+
+ sink = gst_elementfactory_make ("fakesink", "sink");
+ g_assert (sink);
+ g_signal_connect (G_OBJECT (sink), "handoff", G_CALLBACK (handoff), NULL);
+
+ bs = gst_elementfactory_make ("bstest", "bs");
+ g_assert (bs);
+
+ gst_element_connect (src, "src", bs, "sink");
+ gst_element_connect (bs, "src", sink, "sink");
+
+ gst_bin_add (GST_BIN (pipeline), src);
+ gst_bin_add (GST_BIN (pipeline), bs);
+ gst_bin_add (GST_BIN (pipeline), sink);
+
+ walk = params;
+
+ while (walk) {
+ gchar *desc;
+ TestParam *param = (TestParam *) (walk->data);
+
+ integrity_check = param->integrity_check;
+
+ g_print ("\n\nrunning test %d (%d iterations):\n", testnum+1, iterations);
+ desc = create_desc (param);
+ g_print ("%s\n", desc);
+ g_free (desc);
+
+ g_object_set (G_OBJECT (src), "data", param->src_data,
+ "sizetype", param->src_sizetype,
+ "filltype", (integrity_check?5:0),
+ "silent", !verbose, NULL);
+
+ g_object_set (G_OBJECT (bs), "accesspattern", param->bs_accesspattern,
+ "silent", !verbose, NULL);
+
+ g_object_set (G_OBJECT (sink), "dump", dump,
+ "silent", !verbose, NULL);
+
+ run_test (GST_BIN (pipeline), iterations);
+
+ testnum++;
+
+ walk = g_slist_next (walk);
+ }
+
+ g_print ("\n\ndone\n");
+
+ return 0;
+
+}
diff --git a/tests/old/testsuite/bytestream/testfile1 b/tests/old/testsuite/bytestream/testfile1
new file mode 100644
index 0000000000..68a32dd582
--- /dev/null
+++ b/tests/old/testsuite/bytestream/testfile1
@@ -0,0 +1,93 @@
+# lots of parameters here. values for the columns are like:
+#
+# - data property in fakesrc: 1 = allocate, 2 = subbuffer
+# - sizetype property in fakesrc: 2 = fixed, 3 = random
+#
+# - accesspattern for bstest
+# [:...]
+#
+# can be:
+# r = read
+# p = peek
+# pb = peek bytes
+# f = flush
+# can be:
+# = fixed size
+# r = random size
+# < = previous size
+# = this size
+#
+# - integrity check: 0 = no, 1 = yes
+#
+1 2 r 1
+1 2 rr 1
+1 3 r 1
+1 3 rr 1
+2 2 r 1
+2 2 rr 1
+2 3 r 1
+2 3 rr 1
+1 2 p:r< 1
+1 2 pr:r< 1
+1 3 p:r< 1
+1 3 pr:r< 1
+2 2 p:r< 1
+2 2 pr:r< 1
+2 3 p:r< 1
+2 3 pr:r< 1
+1 2 p:rr 1
+1 2 pr:rr 1
+1 3 p:rr 1
+1 3 pr:rr 1
+2 2 p:rr 1
+2 2 pr:rr 1
+2 3 p:rr 1
+2 3 pr:rr 1
+1 2 pb:r 1
+1 2 pbr:r 1
+1 3 pb:r 1
+1 3 pbr:r 1
+2 2 pb:r 1
+2 2 pbr:r 1
+2 3 pb:r 1
+2 3 pbr:r 1
+1 2 pb:rr 1
+1 2 pbr:rr 1
+1 3 pb:rr 1
+1 3 pbr:rr 1
+2 2 pb:rr 1
+2 2 pbr:rr 1
+2 3 pb:rr 1
+2 3 pbr:rr 1
+1 2 p:fr:rr 0
+1 2 pr:fr:rr 0
+1 3 p:fr:rr 0
+1 3 pr:fr:rr 0
+2 2 p:fr:rr 0
+2 2 pr:fr:rr 0
+2 3 p:fr:rr 0
+2 3 pr:fr:rr 0
+1 2 fr:rr 0
+1 2 fr:rr 0
+1 3 fr:rr 0
+1 3 fr:rr 0
+2 2 fr:rr 0
+2 2 fr:rr 0
+2 3 fr:rr 0
+2 3 fr:rr 0
+1 2 fr:fr:rr 0
+1 2 fr:fr:rr 0
+1 3 fr:fr:rr 0
+1 3 fr:fr:rr 0
+2 2 fr:fr:rr 0
+2 2 fr:fr:rr 0
+2 3 fr:fr:rr 0
+2 3 fr:fr:rr 0
+1 2 pbr:pbr:rr 1
+1 2 pbr:pbr:rr 1
+1 3 pbr:pbr:rr 1
+1 3 pbr:pbr:rr 1
+2 2 pbr:pbr:rr 1
+2 2 pbr:pbr:rr 1
+2 3 pbr:pbr:rr 1
+2 3 pbr:pbr:rr 1
diff --git a/tests/sched/Makefile.am b/tests/sched/Makefile.am
index c1ca8520c6..2894b4ca6d 100644
--- a/tests/sched/Makefile.am
+++ b/tests/sched/Makefile.am
@@ -1,4 +1,8 @@
+if GST_DISABLE_LOADSAVE
+noinst_PROGRAMS =
+else
noinst_PROGRAMS = runxml
+endif
# nothing but apps here, this is safe
LIBS += $(GST_LIBS)
diff --git a/testsuite/bytestream/.gitignore b/testsuite/bytestream/.gitignore
new file mode 100644
index 0000000000..7df60c92d6
--- /dev/null
+++ b/testsuite/bytestream/.gitignore
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+test1
diff --git a/testsuite/bytestream/Makefile.am b/testsuite/bytestream/Makefile.am
new file mode 100644
index 0000000000..75aeed7915
--- /dev/null
+++ b/testsuite/bytestream/Makefile.am
@@ -0,0 +1,13 @@
+filterdir = $(libdir)/gst
+
+testprogs = test1
+
+check_PROGRAMS = $(testprogs)
+
+test1_SOURCES = test1.c gstbstest.c mem.c
+test1_LDFLAGS = -L$(top_builddir)/libs/bytestream/ -lgstbytestream
+
+
+# we have nothing but apps here, we can do this safely
+LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
diff --git a/testsuite/bytestream/gstbstest.c b/testsuite/bytestream/gstbstest.c
new file mode 100644
index 0000000000..4199a905f6
--- /dev/null
+++ b/testsuite/bytestream/gstbstest.c
@@ -0,0 +1,407 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen
+ * 2000 Wim Taymans
+ *
+ * gstbstest.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include
+#include
+
+#include
+#include
+
+#define GST_TYPE_BSTEST (gst_bstest_get_type())
+#define GST_BSTEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BSTEST,GstBsTest))
+#define GST_BSTEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BSTEST,GstBsTestClass))
+#define GST_IS_BSTEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BSTEST))
+#define GST_IS_BSTEST_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BSTEST))
+
+typedef struct _GstBsTest GstBsTest;
+typedef struct _GstBsTestClass GstBsTestClass;
+
+struct _GstBsTest
+{
+ GstElement element;
+
+ GstPad *sinkpad;
+ GstPad *srcpad;
+
+ GstByteStream *bs;
+
+ gchar *accesspattern;
+ guint num_patterns;
+ gchar **patterns;
+ guint sizemin;
+ guint sizemax;
+ gint count;
+ gboolean silent;
+};
+
+struct _GstBsTestClass
+{
+ GstElementClass parent_class;
+};
+
+GType gst_bstest_get_type (void);
+
+
+GstElementDetails gst_bstest_details = {
+ "ByteStreamTest",
+ "Filter",
+ "Test for the GstByteStream code",
+ VERSION,
+ "Erik Walthinsen ," "Wim Taymans ",
+ "(C) 2001",
+};
+
+
+/* BsTest signals and args */
+enum
+{
+ /* FILL ME */
+ LAST_SIGNAL
+};
+
+enum
+{
+ ARG_0,
+ ARG_SIZEMIN,
+ ARG_SIZEMAX,
+ ARG_COUNT,
+ ARG_SILENT,
+ ARG_ACCESSPATTERN,
+};
+
+
+static void gst_bstest_class_init (GstBsTestClass * klass);
+static void gst_bstest_init (GstBsTest * bstest);
+
+static void gst_bstest_set_property (GObject * object, guint prop_id, const GValue * value,
+ GParamSpec * pspec);
+static void gst_bstest_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec);
+
+static GstElementStateReturn gst_bstest_change_state (GstElement *element);
+static void gst_bstest_loop (GstElement * element);
+
+static GstElementClass *parent_class = NULL;
+
+// static guint gst_bstest_signals[LAST_SIGNAL] = { 0 };
+
+GType
+gst_bstest_get_type (void)
+{
+ static GType bstest_type = 0;
+
+ if (!bstest_type) {
+ static const GTypeInfo bstest_info = {
+ sizeof (GstBsTestClass), NULL,
+ NULL,
+ (GClassInitFunc) gst_bstest_class_init,
+ NULL,
+ NULL,
+ sizeof (GstBsTest),
+ 0,
+ (GInstanceInitFunc) gst_bstest_init,
+ };
+
+ bstest_type = g_type_register_static (GST_TYPE_ELEMENT, "BSTest", &bstest_info, 0);
+ }
+ return bstest_type;
+}
+
+static void
+gst_bstest_class_init (GstBsTestClass * klass)
+{
+ GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
+
+ gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass*)klass;
+
+ parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
+ g_param_spec_int ("sizemin", "sizemin", "sizemin", 0, G_MAXINT,
+ 0, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
+ g_param_spec_int ("sizemax", "sizemax", "sizemax", 0, G_MAXINT,
+ 384, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ACCESSPATTERN,
+ g_param_spec_string ("accesspattern", "accesspattern", "accesspattern",
+ "r", G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COUNT,
+ g_param_spec_uint ("count", "count", "count",
+ 0, G_MAXUINT, 0, G_PARAM_READWRITE));
+ g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
+ g_param_spec_boolean ("silent", "silent", "silent",
+ FALSE, G_PARAM_READWRITE));
+
+ gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_bstest_set_property);
+ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_bstest_get_property);
+
+ gstelement_class->change_state = gst_bstest_change_state;
+
+}
+
+static GstPadNegotiateReturn
+gst_bstest_negotiate_src (GstPad * pad, GstCaps ** caps, gpointer * data)
+{
+ GstBsTest *bstest;
+
+ bstest = GST_BSTEST (gst_pad_get_parent (pad));
+
+ return gst_pad_negotiate_proxy (pad, bstest->sinkpad, caps);
+}
+
+static GstPadNegotiateReturn
+gst_bstest_negotiate_sink (GstPad * pad, GstCaps ** caps, gpointer * data)
+{
+ GstBsTest *bstest;
+
+ bstest = GST_BSTEST (gst_pad_get_parent (pad));
+
+ return gst_pad_negotiate_proxy (pad, bstest->srcpad, caps);
+}
+
+static void
+gst_bstest_init (GstBsTest * bstest)
+{
+ bstest->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
+ gst_element_add_pad (GST_ELEMENT (bstest), bstest->sinkpad);
+ gst_pad_set_negotiate_function (bstest->sinkpad, gst_bstest_negotiate_sink);
+
+ bstest->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+ gst_element_add_pad (GST_ELEMENT (bstest), bstest->srcpad);
+ gst_pad_set_negotiate_function (bstest->srcpad, gst_bstest_negotiate_src);
+
+ gst_element_set_loop_function (GST_ELEMENT (bstest), gst_bstest_loop);
+
+ bstest->sizemin = 0;
+ bstest->sizemax = 384;
+ bstest->accesspattern = g_strdup ("r");
+ bstest->patterns = g_strsplit (bstest->accesspattern, ":", 0);
+ bstest->count = 5;
+ bstest->silent = FALSE;
+ bstest->bs = NULL;
+}
+
+static guint
+gst_bstest_get_size (GstBsTest *bstest, gchar *sizestring, guint prevsize)
+{
+ guint size;
+
+ if (sizestring[0] == 0) {
+ size = bstest->sizemax;
+ }
+ else if (sizestring[0] == 'r') {
+ size = bstest->sizemin + (guint8)(((gfloat)bstest->sizemax)*rand()/(RAND_MAX + (gfloat)bstest->sizemin));
+ }
+ else if (sizestring[0] == '<') {
+ size = prevsize;
+ }
+ else {
+ size = atoi (sizestring);
+ }
+
+ if (size == 0) size++;
+
+ return size;
+}
+
+static void
+gst_bstest_loop (GstElement * element)
+{
+ GstBsTest *bstest;
+ GstBuffer *buf = NULL;
+
+ g_return_if_fail (element != NULL);
+ g_return_if_fail (GST_IS_BSTEST (element));
+
+ bstest = GST_BSTEST (element);
+
+ do {
+ guint size = 0;
+ guint i = 0;
+
+ while (i < bstest->num_patterns) {
+ buf = NULL;
+
+ if (bstest->patterns[i][0] == 'r') {
+ size = gst_bstest_get_size (bstest, &bstest->patterns[i][1], size);
+ if (!bstest->silent) g_print ("bstest: ***** read %d bytes\n", size);
+ buf = gst_bytestream_read (bstest->bs, size);
+ }
+ else if (bstest->patterns[i][0] == 'f') {
+ size = gst_bstest_get_size (bstest, &bstest->patterns[i][1], size);
+ if (!bstest->silent) g_print ("bstest: ***** flush %d bytes\n", size);
+ gst_bytestream_flush (bstest->bs, size);
+ }
+ else if (!strncmp (bstest->patterns[i], "pb", 2)) {
+ size = gst_bstest_get_size (bstest, &bstest->patterns[i][2], size);
+ if (!bstest->silent) g_print ("bstest: ***** peek bytes %d bytes\n", size);
+ gst_bytestream_peek_bytes (bstest->bs, size);
+ }
+ else if (bstest->patterns[i][0] == 'p') {
+ size = gst_bstest_get_size (bstest, &bstest->patterns[i][1], size);
+ if (!bstest->silent) g_print ("bstest: ***** peek %d bytes\n", size);
+ buf = gst_bytestream_peek (bstest->bs, size);
+ gst_buffer_unref (buf);
+ buf = NULL;
+ }
+
+ if (buf)
+ gst_pad_push (bstest->srcpad, buf);
+
+ i++;
+ }
+ } while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
+}
+
+static void
+gst_bstest_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstBsTest *bstest;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (GST_IS_BSTEST (object));
+
+ bstest = GST_BSTEST (object);
+
+ switch (prop_id) {
+ case ARG_SIZEMIN:
+ bstest->sizemin = g_value_get_int (value);
+ break;
+ case ARG_SIZEMAX:
+ bstest->sizemax = g_value_get_int (value);
+ break;
+ case ARG_ACCESSPATTERN:
+ if (bstest->accesspattern) {
+ g_free (bstest->accesspattern);
+ g_strfreev (bstest->patterns);
+ }
+ if (g_value_get_string (value) == NULL) {
+ gst_element_set_state (GST_ELEMENT (object), GST_STATE_NULL);
+ bstest->accesspattern = NULL;
+ bstest->num_patterns = 0;
+ } else {
+ guint i = 0;
+
+ bstest->accesspattern = g_strdup (g_value_get_string (value));
+ bstest->patterns = g_strsplit (bstest->accesspattern, ":", 0);
+ while (bstest->patterns[i++]);
+ bstest->num_patterns = i-1;
+ }
+ break;
+ case ARG_COUNT:
+ bstest->count = g_value_get_uint (value);
+ break;
+ case ARG_SILENT:
+ bstest->silent = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_bstest_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstBsTest *bstest;
+
+ /* it's not null if we got it, but it might not be ours */
+ g_return_if_fail (GST_IS_BSTEST (object));
+
+ bstest = GST_BSTEST (object);
+
+ switch (prop_id) {
+ case ARG_SIZEMIN:
+ g_value_set_int (value, bstest->sizemin);
+ break;
+ case ARG_SIZEMAX:
+ g_value_set_int (value, bstest->sizemax);
+ break;
+ case ARG_ACCESSPATTERN:
+ g_value_set_string (value, bstest->accesspattern);
+ break;
+ case ARG_COUNT:
+ g_value_set_uint (value, bstest->count);
+ break;
+ case ARG_SILENT:
+ g_value_set_boolean (value, bstest->silent);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstElementStateReturn
+gst_bstest_change_state (GstElement *element)
+{
+ GstBsTest *bstest;
+
+ g_return_val_if_fail (GST_IS_BSTEST (element), GST_STATE_FAILURE);
+
+ bstest = GST_BSTEST (element);
+
+ if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
+ if (bstest->bs) {
+ gst_bytestream_destroy (bstest->bs);
+ bstest->bs = NULL;
+ }
+ }
+ else {
+ if (!bstest->bs) {
+ bstest->bs = gst_bytestream_new (bstest->sinkpad);
+ }
+ }
+
+ if (GST_ELEMENT_CLASS (parent_class)->change_state)
+ return GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+ return GST_STATE_SUCCESS;
+}
+
+static gboolean
+plugin_init (GModule * module, GstPlugin * plugin)
+{
+ GstElementFactory *factory;
+
+ // we need gstbytestream
+ if (!gst_library_load ("gstbytestream")) {
+ g_print ("can't load bytestream\n");
+ return FALSE;
+ }
+
+ /* We need to create an ElementFactory for each element we provide.
+ * This consists of the name of the element, the GType identifier,
+ * and a pointer to the details structure at the top of the file.
+ */
+ factory = gst_elementfactory_new ("bstest", GST_TYPE_BSTEST, &gst_bstest_details);
+ g_return_val_if_fail (factory != NULL, FALSE);
+
+ /* The very last thing is to register the elementfactory with the plugin. */
+ gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
+
+ return TRUE;
+}
+
+GST_PLUGIN_DESC (GST_VERSION_MAJOR, GST_VERSION_MINOR, "bstest", plugin_init);
diff --git a/testsuite/bytestream/mem.c b/testsuite/bytestream/mem.c
new file mode 100644
index 0000000000..d1c36cb5aa
--- /dev/null
+++ b/testsuite/bytestream/mem.c
@@ -0,0 +1,23 @@
+#include
+#include
+#include
+#include
+#include
+
+int vmsize() {
+ int pid,fd,size,i,mem;
+ char filename[17], buf[256], *ptr, *end;
+
+ pid = getpid();
+ snprintf(filename,17,"/proc/%d/stat",pid);
+ fd = open(filename,O_RDONLY);
+ size = read(fd,buf,240);
+ ptr = buf;
+ for (i=0;i<22;i++)
+ ptr = (char *)strchr(ptr,' ') + 1;
+ end = (char *)strchr(ptr,' ');
+ *end = 0;
+ sscanf(ptr,"%d",&mem);
+ close(fd);
+ return mem;
+}
diff --git a/testsuite/bytestream/mem.h b/testsuite/bytestream/mem.h
new file mode 100644
index 0000000000..28999db2c3
--- /dev/null
+++ b/testsuite/bytestream/mem.h
@@ -0,0 +1 @@
+int vmsize();
diff --git a/testsuite/bytestream/test1.c b/testsuite/bytestream/test1.c
new file mode 100644
index 0000000000..0670849e84
--- /dev/null
+++ b/testsuite/bytestream/test1.c
@@ -0,0 +1,230 @@
+#include
+#include
+
+#include
+#include "mem.h"
+
+#define VM_THRES 1000
+#define MAX_CONFIG_LINE 255
+#define MAX_CONFIG_PATTERN 64
+
+typedef struct
+{
+ gint src_data;
+ gint src_sizetype;
+
+ gchar *bs_accesspattern;
+
+ gboolean integrity_check;
+} TestParam;
+
+static GSList *params = NULL;
+
+static guint8 count;
+static guint iterations;
+static gboolean integrity_check = TRUE;
+static gboolean verbose = FALSE;
+static gboolean dump = FALSE;
+
+static void
+handoff (GstElement *element, GstBuffer *buf, GstPad *pad, gpointer data)
+{
+ if (GST_IS_BUFFER (buf)) {
+ if (integrity_check) {
+ gint i;
+ guint8 *ptr = GST_BUFFER_DATA (buf);
+
+ for (i=0; isrc_sizetype == 2 ? "fixed" : "random"),
+ (param->src_data == 1 ? "src" : "subbuffer"),
+ param->bs_accesspattern);
+ return desc;
+}
+
+static gboolean
+read_param_file (gchar *filename)
+{
+ FILE *fp;
+ gchar line[MAX_CONFIG_LINE+1];
+ guint linenr = 0;
+ gchar pattern[MAX_CONFIG_PATTERN];
+ gint data, sizetype, integrity_check;
+ gchar *scan_str;
+ gboolean res = TRUE;
+
+ fp = fopen (filename, "r");
+ if (fp == NULL)
+ return FALSE;
+
+ scan_str = g_strdup_printf ("%%d %%d %%%ds %%d", MAX_CONFIG_PATTERN-1);
+
+ while (fgets (line, MAX_CONFIG_LINE, fp)) {
+ linenr++;
+
+ if (line[0] == '\n' || line[0] == '#')
+ continue;
+
+ if (sscanf (line, scan_str, &data, &sizetype, pattern, &integrity_check) != 4) {
+ g_print ("error on line: %d\n", linenr);
+ res = FALSE;
+ break;
+ }
+ else {
+ TestParam *param = g_malloc (sizeof (TestParam));
+
+ param->src_data = data;
+ param->src_sizetype = sizetype;
+ param->bs_accesspattern = g_strdup (pattern);
+ param->integrity_check = (integrity_check == 0 ? FALSE : TRUE);
+
+ params = g_slist_append (params, param);
+ }
+ }
+ g_free (scan_str);
+
+ return res;
+}
+
+static void
+run_test (GstBin *pipeline, gint iters)
+{
+ gint vm = 0;
+ gint maxiters = iters;
+ gint prev_percent = -1;
+
+ count = 0;
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+
+ while (iters) {
+ gint newvm = vmsize();
+ gint percent;
+
+ percent = (gint)((maxiters-iters+1)*100.0/maxiters);
+
+ if (percent != prev_percent || newvm - vm > VM_THRES) {
+ g_print ("\r%d (delta %d) %.3d%% ", newvm, newvm - vm, percent);
+ prev_percent = percent;
+ vm = newvm;
+ }
+ gst_bin_iterate (pipeline);
+
+ if (iters > 0) iters--;
+ }
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+}
+
+static void
+usage (char *argv[])
+{
+ g_print ("usage: %s [--verbose] [--dump] \n", argv[0]);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GstElement *src;
+ GstElement *sink;
+ GstElement *bs;
+ GstElement *pipeline;
+ gint testnum = 0;
+ GSList *walk;
+ gint arg_walk;
+
+ gst_init (&argc, &argv);
+
+ arg_walk = 1;
+ while ((arg_walk < argc) && (argv[arg_walk][0] == '-')) {
+ if (!strncmp (argv[arg_walk], "--verbose", 9))
+ verbose = TRUE;
+ else if (!strncmp (argv[arg_walk], "--dump", 6))
+ dump = TRUE;
+ else {
+ g_print ("unknown option %s (ignored)\n", argv[arg_walk]);
+ }
+
+ arg_walk++;
+ }
+ if (argc - arg_walk < 2) {
+ usage(argv);
+ return -1;
+ }
+ if (!read_param_file (argv[arg_walk])) {
+ g_print ("error reading file %s\n", argv[arg_walk]);
+ usage (argv);
+ return -1;
+ }
+ arg_walk++;
+ iterations = atoi (argv[arg_walk]);
+
+ pipeline = gst_elementfactory_make ("pipeline", "pipeline");
+ g_assert (pipeline);
+
+ src = gst_elementfactory_make ("fakesrc", "src");
+ g_assert (src);
+
+ sink = gst_elementfactory_make ("fakesink", "sink");
+ g_assert (sink);
+ g_signal_connect (G_OBJECT (sink), "handoff", G_CALLBACK (handoff), NULL);
+
+ bs = gst_elementfactory_make ("bstest", "bs");
+ g_assert (bs);
+
+ gst_element_connect (src, "src", bs, "sink");
+ gst_element_connect (bs, "src", sink, "sink");
+
+ gst_bin_add (GST_BIN (pipeline), src);
+ gst_bin_add (GST_BIN (pipeline), bs);
+ gst_bin_add (GST_BIN (pipeline), sink);
+
+ walk = params;
+
+ while (walk) {
+ gchar *desc;
+ TestParam *param = (TestParam *) (walk->data);
+
+ integrity_check = param->integrity_check;
+
+ g_print ("\n\nrunning test %d (%d iterations):\n", testnum+1, iterations);
+ desc = create_desc (param);
+ g_print ("%s\n", desc);
+ g_free (desc);
+
+ g_object_set (G_OBJECT (src), "data", param->src_data,
+ "sizetype", param->src_sizetype,
+ "filltype", (integrity_check?5:0),
+ "silent", !verbose, NULL);
+
+ g_object_set (G_OBJECT (bs), "accesspattern", param->bs_accesspattern,
+ "silent", !verbose, NULL);
+
+ g_object_set (G_OBJECT (sink), "dump", dump,
+ "silent", !verbose, NULL);
+
+ run_test (GST_BIN (pipeline), iterations);
+
+ testnum++;
+
+ walk = g_slist_next (walk);
+ }
+
+ g_print ("\n\ndone\n");
+
+ return 0;
+
+}
diff --git a/testsuite/bytestream/testfile1 b/testsuite/bytestream/testfile1
new file mode 100644
index 0000000000..68a32dd582
--- /dev/null
+++ b/testsuite/bytestream/testfile1
@@ -0,0 +1,93 @@
+# lots of parameters here. values for the columns are like:
+#
+# - data property in fakesrc: 1 = allocate, 2 = subbuffer
+# - sizetype property in fakesrc: 2 = fixed, 3 = random
+#
+# - accesspattern for bstest
+# [:...]
+#
+# can be:
+# r = read
+# p = peek
+# pb = peek bytes
+# f = flush
+# can be:
+# = fixed size
+# r = random size
+# < = previous size
+# = this size
+#
+# - integrity check: 0 = no, 1 = yes
+#
+1 2 r 1
+1 2 rr 1
+1 3 r 1
+1 3 rr 1
+2 2 r 1
+2 2 rr 1
+2 3 r 1
+2 3 rr 1
+1 2 p:r< 1
+1 2 pr:r< 1
+1 3 p:r< 1
+1 3 pr:r< 1
+2 2 p:r< 1
+2 2 pr:r< 1
+2 3 p:r< 1
+2 3 pr:r< 1
+1 2 p:rr 1
+1 2 pr:rr 1
+1 3 p:rr 1
+1 3 pr:rr 1
+2 2 p:rr 1
+2 2 pr:rr 1
+2 3 p:rr 1
+2 3 pr:rr 1
+1 2 pb:r 1
+1 2 pbr:r 1
+1 3 pb:r 1
+1 3 pbr:r 1
+2 2 pb:r 1
+2 2 pbr:r 1
+2 3 pb:r 1
+2 3 pbr:r 1
+1 2 pb:rr 1
+1 2 pbr:rr 1
+1 3 pb:rr 1
+1 3 pbr:rr 1
+2 2 pb:rr 1
+2 2 pbr:rr 1
+2 3 pb:rr 1
+2 3 pbr:rr 1
+1 2 p:fr:rr 0
+1 2 pr:fr:rr 0
+1 3 p:fr:rr 0
+1 3 pr:fr:rr 0
+2 2 p:fr:rr 0
+2 2 pr:fr:rr 0
+2 3 p:fr:rr 0
+2 3 pr:fr:rr 0
+1 2 fr:rr 0
+1 2 fr:rr 0
+1 3 fr:rr 0
+1 3 fr:rr 0
+2 2 fr:rr 0
+2 2 fr:rr 0
+2 3 fr:rr 0
+2 3 fr:rr 0
+1 2 fr:fr:rr 0
+1 2 fr:fr:rr 0
+1 3 fr:fr:rr 0
+1 3 fr:fr:rr 0
+2 2 fr:fr:rr 0
+2 2 fr:fr:rr 0
+2 3 fr:fr:rr 0
+2 3 fr:fr:rr 0
+1 2 pbr:pbr:rr 1
+1 2 pbr:pbr:rr 1
+1 3 pbr:pbr:rr 1
+1 3 pbr:pbr:rr 1
+2 2 pbr:pbr:rr 1
+2 2 pbr:pbr:rr 1
+2 3 pbr:pbr:rr 1
+2 3 pbr:pbr:rr 1
diff --git a/tools/Makefile.am b/tools/Makefile.am
index b45f29d3de..bef06f9476 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -5,6 +5,12 @@ else
GST_REGISTRY_SRC = gstreamer-register
endif
+if GST_DISABLE_LOADSAVE
+GST_LOADSAVE_SRC =
+else
+GST_LOADSAVE_SRC = gstreamer-compprep
+endif
+
if USE_GLIB2
GST_GUI_LAUNCH =
else
@@ -12,16 +18,16 @@ GST_GUI_LAUNCH = gstreamer-guilaunch
endif
bin_PROGRAMS = gstreamer-launch \
- $(GST_GUI_LAUNCH) \
+ $(GST_GUI_LAUNCH) \
$(GST_REGISTRY_SRC) \
gstreamer-inspect \
- gstreamer-compprep \
+ $(GST_LOADSAVE_SRC) \
gstreamer-complete
man_MANS = gstreamer-launch.1 gstreamer-register.1 gstreamer-inspect.1 \
gstreamer-complete.1 gstreamer-compprep.1
LDADD = $(GST_LIBS)
-CFLAGS = $(LIBGST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\"
+CFLAGS = $(LIBGST_CFLAGS) -DGST_CONFIG_DIR=\"$(GST_CONFIG_DIR)\"
EXTRA_DIST = $(man_MANS)
diff --git a/tools/gstreamer-inspect.c b/tools/gstreamer-inspect.c
index 2ec45ac589..6ac84be18a 100644
--- a/tools/gstreamer-inspect.c
+++ b/tools/gstreamer-inspect.c
@@ -221,10 +221,12 @@ print_element_info (GstElementFactory *factory)
printf(" Has change_state() function: %s\n",
GST_DEBUG_FUNCPTR_NAME(gstelement_class->change_state));
+#ifndef GST_DISABLE_LOADSAVE
printf(" Has custom save_thyself() function: %s\n",
GST_DEBUG_FUNCPTR_NAME(gstobject_class->save_thyself));
printf(" Has custom restore_thyself() function: %s\n",
GST_DEBUG_FUNCPTR_NAME(gstobject_class->restore_thyself));
+#endif
diff --git a/tools/gstreamer-launch.c b/tools/gstreamer-launch.c
index af7a494685..821bb38c8a 100644
--- a/tools/gstreamer-launch.c
+++ b/tools/gstreamer-launch.c
@@ -61,7 +61,11 @@ arg_search (GstBin *bin, gchar *argname, found_handler handler, void *priv)
gboolean
idle_func (gpointer data)
{
- return gst_bin_iterate (GST_BIN (data));
+ if (!gst_bin_iterate (GST_BIN (data))) {
+ gtk_main_quit ();
+ return FALSE;
+ }
+ return TRUE;
}
void
@@ -148,9 +152,11 @@ main(int argc, char *argv[])
gst_parse_launch (cmdline, GST_BIN (pipeline));
+#ifndef GST_DISABLE_LOADSAVE
if (save_pipeline) {
xmlSaveFile (savefile, gst_xml_write (pipeline));
}
+#endif
if (run_pipeline) {
arg_search(GST_BIN(pipeline),"xid",xid_handler,NULL);