# 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
])
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,,
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)
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
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")
libs/putbits/Makefile
libs/idct/Makefile
libs/audio/Makefile
+libs/bytestream/Makefile
libs/control/Makefile
plugins/Makefile
plugins/a52dec/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
</para>
-@name:
+@feature:
@longdesc:
@type:
@Returns:
-<!-- ##### FUNCTION gst_autoplugfactory_save_thyself ##### -->
-<para>
-
-</para>
-
-@factory:
-@parent:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_autoplugfactory_load_thyself ##### -->
-<para>
-
-</para>
-
-@parent:
-@Returns:
-
-
</para>
+@data_type:
@lock:
@data:
@size:
</para>
@pool:
+@location:
+@size:
@Returns:
</para>
+@buf:
+@buf2:
+@Returns:
+<!-- # Unused Parameters # -->
@buffer:
@append:
-@Returns:
<!-- ##### FUNCTION gst_buffer_ref ##### -->
</para>
@lock:
-@new_user_data:
-@destroy_user_data:
-@destroy_buffer:
-
-<!-- ##### USER_FUNCTION GstBufferPoolCreateFunction ##### -->
-<para>
-The function called when a buffer has to be created for this pool.
-</para>
-
-@pool: the pool from which to create the buffer
-@user_data: any user data
-@Returns: a new buffer from the pool
-
-
-<!-- ##### USER_FUNCTION GstBufferPoolDestroyFunction ##### -->
-<para>
-This function will be called when the given buffer has to be returned to
-the pool.
-</para>
-
-@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:
<!-- ##### FUNCTION gst_buffer_pool_new ##### -->
<para>
@Returns:
-<!-- ##### FUNCTION gst_buffer_pool_new_buffer ##### -->
-<para>
-
-</para>
-
-@pool:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_buffer_pool_destroy_buffer ##### -->
-<para>
-
-</para>
-
-@pool:
-@buffer:
-
-
<!-- ##### FUNCTION gst_buffer_pool_ref ##### -->
<para>
@pool:
-<!-- ##### FUNCTION gst_buffer_pool_set_create_function ##### -->
-<para>
-
-</para>
-
-@pool:
-@create:
-@user_data:
-
-
-<!-- ##### FUNCTION gst_buffer_pool_set_destroy_function ##### -->
-<para>
-
-</para>
-
-@pool:
-@destroy:
-@user_data:
-
-
<!-- ##### FUNCTION gst_buffer_pool_destroy ##### -->
<para>
</para>
-@oldpool:
@buffer_size:
@pool_size:
@Returns:
+<!-- # Unused Parameters # -->
+@oldpool:
Get/set the current offset in the file.
</para>
-<!-- ##### ARG GstDiskSrc:size ##### -->
+<!-- ##### ARG GstDiskSrc:filesize ##### -->
<para>
-Get the size of the file.
+
</para>
GstElementDetails struct for the element.
</para>
-@name:
+@feature:
@type:
@details:
@padtemplates:
@element: The element in question.
-<!-- ##### FUNCTION gst_element_new ##### -->
-<para>
-
-</para>
-
-@Returns:
-
-
<!-- ##### MACRO gst_element_destroy ##### -->
<para>
@Returns:
-<!-- ##### FUNCTION gst_elementfactory_destroy ##### -->
-<para>
-
-</para>
-
-@elementfactory:
-
-
<!-- ##### FUNCTION gst_elementfactory_add_padtemplate ##### -->
<para>
@Returns:
-<!-- ##### FUNCTION gst_elementfactory_save_thyself ##### -->
-<para>
-
-</para>
-
-@factory:
-@parent:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_elementfactory_load_thyself ##### -->
-<para>
-
-</para>
-
-@parent:
-@Returns:
-
-
<!-- ##### SIGNAL GstElement::state-change ##### -->
<para>
Is trigered whenever the state of an element changes
@gstfakesink: the object which received the signal.
@arg1:
-<!-- ##### ARG GstFakeSink:num_sinks ##### -->
+<!-- ##### ARG GstFakeSink:num-sinks ##### -->
<para>
</para>
@gstfakesrc: the object which received the signal.
@arg1:
-<!-- ##### ARG GstFakeSrc:num_sources ##### -->
+<!-- ##### ARG GstFakeSrc:num-sources ##### -->
<para>
</para>
-<!-- ##### ARG GstFakeSrc:loop_based ##### -->
+<!-- ##### ARG GstFakeSrc:loop-based ##### -->
<para>
</para>
</para>
-<!-- ##### ARG GstFakeSrc:num_buffers ##### -->
+<!-- ##### ARG GstFakeSrc:num-buffers ##### -->
<para>
</para>
@gstidentity: the object which received the signal.
@arg1:
-<!-- ##### ARG GstIdentity:loop_based ##### -->
+<!-- ##### ARG GstIdentity:loop-based ##### -->
<para>
</para>
-<!-- ##### ARG GstIdentity:sleep_time ##### -->
+<!-- ##### ARG GstIdentity:sleep-time ##### -->
<para>
</para>
@obj: The Object to check
-<!-- ##### FUNCTION gst_object_new ##### -->
-<para>
-
-</para>
-
-@Returns:
-
-
<!-- ##### FUNCTION gst_object_check_uniqueness ##### -->
<para>
@size: the size of the region to get
-<!-- ##### USER_FUNCTION GstPadQoSFunction ##### -->
-<para>
-The function that will be called when a QoS message is sent.
-</para>
-
-@pad: the pad that sent the QoS message
-@qos_message: the message
-
-
-<!-- ##### USER_FUNCTION GstPadEOSFunction ##### -->
-<para>
-The function that will be called in an EOS case.
-</para>
-
-@pad: the pad that needs to be set to EOS state
-@Returns: TRUE if EOS was successful, FALSE otherwise
-
-
<!-- ##### USER_FUNCTION GstPadNewCapsFunction ##### -->
<para>
The function that will be called when the caps of the pad has
@Returns: The result of the negotiation process
-<!-- ##### USER_FUNCTION GstPadPushFunction ##### -->
-<para>
-
-The function that will be called when pushing a buffers.
-</para>
-
-@pad: the pad to push
-@buf: a GstBuffer to push
-
-
-<!-- ##### USER_FUNCTION GstPadPullFunction ##### -->
-<para>
-The function that will be called when pulling buffers.
-</para>
-
-@pad: the pad to pull
-@Returns: a GstBuffer
-
-
<!-- ##### ENUM GstRegionType ##### -->
<para>
the region types for #gst_pad_pullregion.
@nego:
-<!-- ##### FUNCTION gst_pad_set_qos_function ##### -->
-<para>
-
-</para>
-
-@pad:
-@qos:
-
-
-<!-- ##### FUNCTION gst_pad_set_eos_function ##### -->
-<para>
-
-</para>
-
-@pad:
-@eos:
-
-
<!-- ##### FUNCTION gst_pad_set_newcaps_function ##### -->
<para>
@Returns:
-<!-- ##### FUNCTION gst_pad_set_eos ##### -->
-<para>
-
-</para>
-
-@pad:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_pad_handle_qos ##### -->
-<para>
-
-</para>
-
-@pad:
-@qos_message:
-
-
-<!-- ##### MACRO gst_pad_eos ##### -->
-<para>
-Call the EOS function of the pad
-</para>
-
-@pad: the pad to call the eos function of.
-
-
<!-- ##### FUNCTION gst_pad_load_and_connect ##### -->
<para>
@Returns:
-<!-- ##### FUNCTION gst_pad_eos_func ##### -->
-<para>
-
-</para>
-
-@pad:
-@Returns:
-
-
<!-- ##### STRUCT GstRealPad ##### -->
<para>
@len:
@sched:
@chainfunc:
+@chainhandler:
@getfunc:
+@gethandler:
+@eventfunc:
+@eventhandler:
@getregionfunc:
-@qosfunc:
-@eosfunc:
-@pushfunc:
-@pullfunc:
@pullregionfunc:
@negotiatefunc:
@newcapsfunc:
@pad: the real pad to query.
-<!-- ##### MACRO GST_RPAD_PUSHFUNC ##### -->
-<para>
-Get the pushfunction of the real pad.
-</para>
-
-@pad: the real pad to query.
-
-
-<!-- ##### MACRO GST_RPAD_PULLFUNC ##### -->
-<para>
-Get the pullfunction of the real pad.
-</para>
-
-@pad: the real pad to query.
-
-
<!-- ##### MACRO GST_RPAD_PULLREGIONFUNC ##### -->
<para>
Get the pullregion function of the real pad.
@pad: the real pad to query.
-<!-- ##### MACRO GST_RPAD_QOSFUNC ##### -->
-<para>
-Get the QoS function of the real pad.
-</para>
-
-@pad: the real pad to query.
-
-
-<!-- ##### MACRO GST_RPAD_EOSFUNC ##### -->
-<para>
-Get the EOS function of the real pad.
-</para>
-
-@pad: the real pad to query.
-
-
<!-- ##### MACRO GST_RPAD_NEGOTIATEFUNC ##### -->
<para>
Get the negotiate function from the real pad.
@name:
@longname:
@filename:
-@types:
-@numtypes:
-@elements:
-@numelements:
-@numautopluggers:
+@features:
+@numfeatures:
+@module:
<!-- ##### USER_FUNCTION GstPluginInitFunc ##### -->
<para>
@Returns:
-<!-- ##### FUNCTION gst_plugin_add_factory ##### -->
-<para>
-
-</para>
-
-@plugin:
-@factory:
-
-
-<!-- ##### FUNCTION gst_plugin_add_type ##### -->
-<para>
-
-</para>
-
-@plugin:
-@factory:
-
-
-<!-- ##### FUNCTION gst_plugin_add_autoplugger ##### -->
-<para>
-
-</para>
-
-@plugin:
-@factory:
-
-
<!-- ##### FUNCTION gst_plugin_find ##### -->
<para>
@Returns:
-<!-- ##### FUNCTION gst_plugin_get_factory_list ##### -->
-<para>
-
-</para>
-
-@plugin:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_plugin_get_type_list ##### -->
-<para>
-
-</para>
-
-@plugin:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_plugin_get_autoplug_list ##### -->
-<para>
-
-</para>
-
-@plugin:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_plugin_load_elementfactory ##### -->
-<para>
-
-</para>
-
-@name:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_plugin_load_typefactory ##### -->
-<para>
-
-</para>
-
-@mime:
-
-
-<!-- ##### FUNCTION gst_plugin_load_autoplugfactory ##### -->
-<para>
-
-</para>
-
-@name:
-@Returns:
-
-
<!-- ##### FUNCTION gst_plugin_load_thyself ##### -->
<para>
Get the number of buffers in the queue.
</para>
-<!-- ##### ARG GstQueue:max_level ##### -->
+<!-- ##### ARG GstQueue:max-level ##### -->
<para>
Specify the maximum number of buffers in the queue before the queue
blocks.
-<!-- ##### FUNCTION gst_fakesink_chain ##### -->
+<!-- ##### SECTION ./tmpl/GstElement.sgml:Long_Description ##### -->
<para>
</para>
-@pad:
-@buf:
-<!-- ##### ARG GstTypeFind:type ##### -->
+<!-- ##### SECTION ./tmpl/GstElement.sgml:See_Also ##### -->
<para>
-Query the element for the current mime type
+
</para>
-<!-- ##### ARG GstAudioSink:mute ##### -->
+<!-- ##### SECTION ./tmpl/GstElement.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/GstElement.sgml:Title ##### -->
+GstElement
+
+
+<!-- ##### SECTION ./tmpl/audioraw.sgml:Long_Description ##### -->
+<para>
+Information about audio buffers.
+</para>
+
+
+<!-- ##### SECTION ./tmpl/audioraw.sgml:See_Also ##### -->
<para>
</para>
-<!-- ##### STRUCT GstFakeSrc ##### -->
+<!-- ##### SECTION ./tmpl/audioraw.sgml:Short_Description ##### -->
+Information about audio buffers.
+
+
+<!-- ##### SECTION ./tmpl/audioraw.sgml:Title ##### -->
+audioraw
+
+
+<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:Long_Description ##### -->
+<para>
+Reads data from a file. You can seek to a specific location by setting
+the offset.
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:See_Also ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_tee_get_type ##### -->
+<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:Title ##### -->
+GstAsyncDiskSrc
+
+
+<!-- ##### SECTION ./tmpl/gstaudiosink.sgml:Long_Description ##### -->
<para>
</para>
-@Returns:
-<!-- ##### MACRO GST_IS_SINK ##### -->
+<!-- ##### SECTION ./tmpl/gstaudiosink.sgml:See_Also ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_META ##### -->
+<!-- ##### SECTION ./tmpl/gstaudiosink.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/gstaudiosink.sgml:Title ##### -->
+GstAudioSink
+
+
+<!-- ##### SECTION ./tmpl/gstaudiosrc.sgml:Long_Description ##### -->
<para>
</para>
-@meta:
-<!-- ##### FUNCTION gst_caps_list_check_compatibility ##### -->
+<!-- ##### SECTION ./tmpl/gstaudiosrc.sgml:See_Also ##### -->
<para>
</para>
-@fromcaps:
-@tocaps:
-@Returns:
-<!-- ##### MACRO GST_IS_CONNECTION ##### -->
+<!-- ##### SECTION ./tmpl/gstaudiosrc.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/gstaudiosrc.sgml:Title ##### -->
+GstAudioSrc
+
+
+<!-- ##### SECTION ./tmpl/gstcolorspace.sgml:Long_Description ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_TYPE_FAKESINK ##### -->
+<!-- ##### SECTION ./tmpl/gstcolorspace.sgml:See_Also ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_pad_remove_ghost_parent ##### -->
+<!-- ##### SECTION ./tmpl/gstcolorspace.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/gstcolorspace.sgml:Title ##### -->
+GstColorSpace
+
+
+<!-- ##### SECTION ./tmpl/gstconnection.sgml:Long_Description ##### -->
<para>
+A connection is a bas class for a generic connection between
+elements. A connection is typically a bas class for queues.
</para>
-@pad:
-@parent:
-<!-- ##### FUNCTION gst_fdsink_chain ##### -->
+<!-- ##### SECTION ./tmpl/gstconnection.sgml:See_Also ##### -->
<para>
</para>
-@pad:
-@buf:
-<!-- ##### FUNCTION gst_identity_chain ##### -->
+<!-- ##### SECTION ./tmpl/gstconnection.sgml:Short_Description ##### -->
+Generic connection between elements.
+
+
+<!-- ##### SECTION ./tmpl/gstconnection.sgml:Title ##### -->
+GstConnection
+
+
+<!-- ##### SECTION ./tmpl/gstesdsink.sgml:Long_Description ##### -->
<para>
</para>
-@pad:
-@buf:
-<!-- ##### FUNCTION gst_connection_get_type ##### -->
+<!-- ##### SECTION ./tmpl/gstesdsink.sgml:See_Also ##### -->
<para>
</para>
-@Returns:
-<!-- ##### FUNCTION gst_audiosink_chain ##### -->
+<!-- ##### SECTION ./tmpl/gstesdsink.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/gstesdsink.sgml:Title ##### -->
+GstEsdSink
+
+
+<!-- ##### SECTION ./tmpl/gstfilter.sgml:Long_Description ##### -->
+<para>
+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.
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gstfilter.sgml:See_Also ##### -->
<para>
</para>
-@pad:
-@buf:
-<!-- ##### MACRO GST_PIPELINE_CLASS ##### -->
+<!-- ##### SECTION ./tmpl/gstfilter.sgml:Short_Description ##### -->
+Take data in and spit data out
+
+
+<!-- ##### SECTION ./tmpl/gstfilter.sgml:Title ##### -->
+GstFilter
+
+
+<!-- ##### SECTION ./tmpl/gstgetbits.sgml:Long_Description ##### -->
<para>
</para>
-@klass:
-<!-- ##### FUNCTION gst_elementfactory_add_src ##### -->
+<!-- ##### SECTION ./tmpl/gstgetbits.sgml:See_Also ##### -->
<para>
</para>
-@elementfactory:
-@id:
-<!-- ##### STRUCT GstConnectionClass ##### -->
+<!-- ##### SECTION ./tmpl/gstgetbits.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/gstgetbits.sgml:Title ##### -->
+GstGetbits
+
+
+<!-- ##### SECTION ./tmpl/gstmeta.sgml:Long_Description ##### -->
<para>
+The point of the metadata is to provide some context for each buffer. In
+the case of audio data, for instance, it would provide the samplerate, bit
+depth, and channel count.
+</para>
+<para>
+The trick is that there may be multiple types of metadata ganged onto a
+single buffer. This is why they're going to be a GList. This does mean
+extra overhead in all cases, but I think it's minimal. The GList type
+uses a chunk allocater so we're not wasting too much memory or time when
+adding to the list.
</para>
+<para>
+The trick is dealing with these structs as they pass through a pipeline,
+since they have potentially different mutability properties. For
+instance, if you've got a mp3 decoder connected to a tee, which sends the
+buffers off to both the decoder and a spectrum analyzer (and then a
+visualization element). The preferred setup would be where every time a
+audio/raw metadata comes down the pipe (indicating a potential change in
+audio format), the audiosink and spectrum would just save off pointers.
+</para>
-<!-- ##### ARG GstSineSrc:channels ##### -->
<para>
-The number of channels.
+So when exactly does this metadata go away (deallocated)? Well, that
+means metadata has to be refcounted. But that gets rather hairy. OK, in
+the simple case you create a metadata struct, it comes with refcount set
+to 1. You pass it through, it stays one, eventually someone drops the
+last reference on the buffer it's tied to, you free the metadata too.
+Easy. What if you tee? You could go through and for every metadata in
+the buffer, increment the refcount by the same as the buffer. So in the
+above case (tee'd), the audiosink and spectrum would get the buffer with a
+refcount of 2, and it'd have a metadata with refcount 2. Do they ref it
+each themselves, then unref the buffer? Or do they remove the metadata?
+Removing the metadata would require a buffer CoW, which would suck, so
+yes, they'd just ref the metadata.
+</para>
+
+<para>
+But.... what if they're all in different threads? Then we're off into
+the magical world of mutexes. Everything with a refcount in a threaded
+world must be mutexed, else you can do atomic increment and atomic
+dec and test. Can this be done from C easily? Perhaps it needs to be found
+from kernel includes via autoconf?
+</para>
+
+<para>
+The goal in designing the way metadata will be defined and used is to keep
+it as simple as possible. The basis for accomplishing this is the fact
+that in order to actually use (rather than just pass) the metadata, you
+have to know what the fields are, which means you have to have compiled in
+support for that metadata at build time. Therefore, if you're using
+metadata, you must have build-time access to the necessary include file
+that defines it.
+</para>
+
+<para>
+So, given that you've got an include file, it would be nice if the whole
+thing could be contained there. This would limit the need to be linked
+against something, or have load-time requirements as to that has to be
+loaded before you are.
+</para>
+
+<para>
+Given that really all metadata is is a region of memory of a given size
+with a certain signature, this isn't all that hard. First you lay out the
+struct that defines the metadata. Then you set up #defines that expand to
+the size of the struct in question, as well as the four-cc code that
+defines the type.
+</para>
+
+<para>
+The work is done by a few #defines, a la the #defines used in all Gtk
+objects. The first is a NEW() method that allocates the memory for the
+metadata and fills in all the normal fields (type, size, utility
+functions). Because of the way it's defined (as a #define, no less),
+you'll have to invoke it as META_NEW(meta), since it can't return()
+anything.
+</para>
+
+<para>
+Another #define will check to make sure a meta is indeed that type by
+verifying the type code and size. Theoretically, meta types can overlap
+with the same fourcc code, as long as they have different sizes. But I
+probably ought to have a global public registry so people writing things
+don't conflict. MSFT got that right, at least.
+</para>
+
+<para>
+So, a hairy problem is what to do when there are utility functions
+associated with one of these things. One option is to not bother with
+them. This is very likely a possible solution, since metadata is supposed
+to be flat memory of a given size. Not much to do to either free or copy
+it, is there?
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gstmeta.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gstmeta.sgml:Short_Description ##### -->
+Provide context for buffers
+
+
+<!-- ##### SECTION ./tmpl/gstmeta.sgml:Title ##### -->
+GstMeta
+
+
+<!-- ##### SECTION ./tmpl/gstsink.sgml:Long_Description ##### -->
+<para>
+The sink is the end of the filter graph. A typical sink would be an audio
+or a video card.
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gstsink.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gstsink.sgml:Short_Description ##### -->
+The end point of a filter graph
+
+
+<!-- ##### SECTION ./tmpl/gstsink.sgml:Title ##### -->
+GstSink
+
+
+<!-- ##### SECTION ./tmpl/gstsrc.sgml:Long_Description ##### -->
+<para>
+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.
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gstsrc.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/gstsrc.sgml:Short_Description ##### -->
+The start point of a filter graph
+
+
+<!-- ##### SECTION ./tmpl/gstsrc.sgml:Title ##### -->
+GstSrc
+
+
+<!-- ##### SECTION ./tmpl/plugin.sgml:Long_Description ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/plugin.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/plugin.sgml:Short_Description ##### -->
+
+
+
+<!-- ##### SECTION ./tmpl/plugin.sgml:Title ##### -->
+plugin
+
+
+<!-- ##### SECTION ./tmpl/spectrum.sgml:Long_Description ##### -->
+<para>
+Frequencies of a spectrum analysis.
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/spectrum.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/spectrum.sgml:Short_Description ##### -->
+Frequencies of a spectrum analysis.
+
+
+<!-- ##### SECTION ./tmpl/spectrum.sgml:Title ##### -->
+spectrum
+
+
+<!-- ##### SECTION ./tmpl/videoraw.sgml:Long_Description ##### -->
+<para>
+Information about video buffers.
+</para>
+
+
+<!-- ##### SECTION ./tmpl/videoraw.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/videoraw.sgml:Short_Description ##### -->
+Information about video buffers.
+
+
+<!-- ##### SECTION ./tmpl/videoraw.sgml:Title ##### -->
+videoraw
+
+
+<!-- ##### MACRO COTHREAD_MAXTHREADS ##### -->
+<para>
+The maximum number of cothreads we are going to support.
+</para>
+
+
+<!-- ##### MACRO COTHREAD_STACKSIZE ##### -->
+<para>
+The default stack size of a cothread.
</para>
@format: the format specification as in g_print
@args...: arguments
-<!-- ##### SECTION ./tmpl/gstesdsink.sgml:Title ##### -->
-GstEsdSink
+<!-- ##### MACRO DEBUG_ENTER ##### -->
+<para>
+
+</para>
+
+@format:
+@args...:
+
+<!-- ##### MACRO DEBUG_ENTER_STRING ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO DEBUG_LEAVE ##### -->
+<para>
+
+</para>
+
+@format:
+@args...:
+
+<!-- ##### MACRO DEBUG_LEAVE_STRING ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### MACRO DEBUG_NOPREFIX ##### -->
+<para>
+
+</para>
+
+@format:
+@args...:
+
+<!-- ##### MACRO DEBUG_SET_STRING ##### -->
+<para>
+
+</para>
+
+@format:
+@args...:
+
+<!-- ##### MACRO ERROR ##### -->
+<para>
+
+</para>
+
+@element:
+@format:
+@args...:
+
+<!-- ##### MACRO ERROR_OBJECT ##### -->
+<para>
+
+</para>
+
+@element:
+@object:
+@format:
+@args...:
+
+<!-- ##### MACRO GST_ASYNCDISKSRC ##### -->
+<para>
+
+</para>
+
+@obj:
+
+<!-- ##### MACRO GST_ASYNCDISKSRC_CLASS ##### -->
+<para>
+
+</para>
+
+@klass:
+
+<!-- ##### MACRO GST_AUDIOSINK ##### -->
+<para>
+
+</para>
+
+@obj:
+
+<!-- ##### MACRO GST_AUDIOSINK_CLASS ##### -->
+<para>
+
+</para>
+
+@klass:
+
+<!-- ##### MACRO GST_AUDIOSRC ##### -->
+<para>
+
+</para>
+
+@obj:
+
+<!-- ##### MACRO GST_AUDIOSRC_CLASS ##### -->
+<para>
+
+</para>
+@klass:
-<!-- ##### MACRO GST_TYPE_IDENTITY ##### -->
+<!-- ##### MACRO GST_BIN ##### -->
<para>
</para>
+@obj:
-<!-- ##### FUNCTION gst_type_save_thyself ##### -->
+<!-- ##### MACRO GST_BIN_CLASS ##### -->
<para>
</para>
-@type:
-@parent:
-@Returns:
+@klass:
-<!-- ##### FUNCTION gst_audiosrc_push ##### -->
+<!-- ##### MACRO GST_BUFFER ##### -->
<para>
</para>
-@src:
+@buf:
-<!-- ##### MACRO GST_IS_FAKESRC_CLASS ##### -->
+<!-- ##### MACRO GST_BUFFER_POOL ##### -->
<para>
</para>
-@obj:
+@buf:
-<!-- ##### SECTION ./tmpl/gstaudiosrc.sgml:See_Also ##### -->
+<!-- ##### MACRO GST_BUFFER_TYPE ##### -->
<para>
-
+Retrieves the type id of the data in the buffer.
</para>
+@buf: GstBuffer
-<!-- ##### MACRO GST_AUDIOSINK ##### -->
+<!-- ##### MACRO GST_CONNECTION ##### -->
<para>
</para>
@obj:
-<!-- ##### SIGNAL GstSrc::eos ##### -->
+<!-- ##### MACRO GST_CONNECTION_CLASS ##### -->
<para>
-An eos signal is triggered whenever the GstSrc has reached the end of
-the stream.
</para>
-@gstsrc: the object which received the signal.
-@arg1: the object which received the signal
+@klass:
-<!-- ##### TYPEDEF GstCapsFactoryEntry ##### -->
+<!-- ##### MACRO GST_CPU_FLAG_MMX ##### -->
<para>
-
+A flag indicating that MMX instructions are supported.
</para>
-<!-- ##### FUNCTION gst_disksrc_get_type ##### -->
+<!-- ##### MACRO GST_CPU_FLAG_SSE ##### -->
<para>
-
+A flag indicating that SSE instructions are supported.
</para>
-@Returns:
-<!-- ##### MACRO GST_IS_DISKSRC_CLASS ##### -->
+<!-- ##### MACRO GST_DEBUG_ENTER_STRING ##### -->
<para>
-
+Combine #GST_DEBUG_ENTER and #GST_DEBUG_SET_STRING.
</para>
-@obj:
-<!-- ##### SECTION ./tmpl/gstmeta.sgml:Short_Description ##### -->
-Provide context for buffers
+<!-- ##### MACRO GST_DEBUG_LEAVE_STRING ##### -->
+<para>
+
+</para>
-<!-- ##### MACRO DEBUG_ENTER_STRING ##### -->
+<!-- ##### MACRO GST_DEBUG_NOPREFIX ##### -->
<para>
</para>
+@cat:
+@format:
+@args...:
-<!-- ##### SECTION ./tmpl/audioraw.sgml:See_Also ##### -->
+<!-- ##### MACRO GST_DEBUG_PREFIX ##### -->
<para>
</para>
+@cat:
+@format:
+@args...:
-<!-- ##### FUNCTION gst_padtemplate_create ##### -->
+<!-- ##### MACRO GST_DEBUG_SET_STRING ##### -->
<para>
-
+Set the debug string for the current function, typically containing the arguments
+to the current function, i.e. "('element')"
</para>
-@name_template:
-@direction:
-@presence:
-@caps:
-@Returns:
+@format: printf-style format string
+@args...: printf arguments
-<!-- ##### MACRO GST_IS_ESDSINK_CLASS ##### -->
+<!-- ##### MACRO GST_DISKSRC ##### -->
<para>
</para>
@obj:
-<!-- ##### SECTION ./tmpl/gstgetbits.sgml:See_Also ##### -->
+<!-- ##### MACRO GST_DISKSRC_CLASS ##### -->
<para>
</para>
+@klass:
-<!-- ##### MACRO GST_SRC ##### -->
+<!-- ##### MACRO GST_ELEMENT ##### -->
<para>
</para>
@obj:
-<!-- ##### FUNCTION gst_sink_new ##### -->
+<!-- ##### MACRO GST_ELEMENT_CLASS ##### -->
<para>
</para>
-@name:
-@Returns:
+@klass:
-<!-- ##### MACRO GST_PAD_CLASS ##### -->
+<!-- ##### MACRO GST_ELEMENT_IS_MULTI_IN ##### -->
<para>
+Query whether this object has multiple input pads.
</para>
-@klass:
+@obj: Element to query for multiple input pads.
-<!-- ##### FUNCTION plugin_load_all ##### -->
+<!-- ##### MACRO GST_ESDSINK ##### -->
<para>
</para>
+@obj:
-<!-- ##### MACRO GST_SINESRC_CLASS ##### -->
+<!-- ##### MACRO GST_ESDSINK_CLASS ##### -->
<para>
</para>
-@klass:
+@klass: <<<<<<< gstreamer-unused.sgml
-<!-- ##### FUNCTION gst_pad_save_thyself ##### -->
+<!-- ##### MACRO GST_FAKESINK ##### -->
<para>
</para>
-@pad:
-@parent:
-@Returns:
+@obj:
-<!-- ##### MACRO GST_IS_AUDIOSINK_CLASS ##### -->
+<!-- ##### MACRO GST_FAKESINK_CLASS ##### -->
<para>
</para>
-@obj:
+@klass:
-<!-- ##### STRUCT GstDiskSrc ##### -->
+<!-- ##### MACRO GST_FAKESRC ##### -->
<para>
</para>
+@obj:
-<!-- ##### ARG GstDiskSink:location ##### -->
+<!-- ##### MACRO GST_FAKESRC_CLASS ##### -->
<para>
-The filename to write to.
+
</para>
+@klass:
-<!-- ##### MACRO GST_IS_SRC_CLASS ##### -->
+<!-- ##### MACRO GST_FDSINK ##### -->
<para>
</para>
@obj:
-<!-- ##### ARG GstAsyncDiskSrc:bytesperread ##### -->
+<!-- ##### MACRO GST_FDSINK_CLASS ##### -->
<para>
-Specify how many bytes to read at a time.
+
</para>
+@klass:
-<!-- ##### FUNCTION gst_filter_new ##### -->
+<!-- ##### MACRO GST_FDSRC ##### -->
<para>
</para>
-@name:
-@Returns:
+@obj:
-<!-- ##### SECTION ./tmpl/gstesdsink.sgml:Short_Description ##### -->
+<!-- ##### MACRO GST_FDSRC_CLASS ##### -->
+<para>
+</para>
+@klass:
-<!-- ##### FUNCTION gst_sink_get_type ##### -->
+<!-- ##### MACRO GST_FILTER ##### -->
<para>
</para>
-@Returns:
+@obj:
-<!-- ##### FUNCTION gst_queue_push ##### -->
+<!-- ##### MACRO GST_FILTER_CLASS ##### -->
<para>
</para>
-@connection:
+@klass:
<!-- ##### MACRO GST_FILTER_FLAG_LAST ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_audiosink_set_channels ##### -->
+<!-- ##### MACRO GST_HTTPSRC ##### -->
+>>>>>>> 1.23.2.3
<para>
</para>
-@audiosink:
-@channels:
+@obj:
-<!-- ##### SECTION ./tmpl/gstconnection.sgml:Short_Description ##### -->
-Generic connection between elements.
+<!-- ##### MACRO GST_HTTPSRC_CLASS ##### -->
+<para>
+</para>
-<!-- ##### STRUCT GstSinkClass ##### -->
+@klass:
+
+<!-- ##### MACRO GST_IDENTITY ##### -->
<para>
</para>
+@obj:
-<!-- ##### STRUCT GstFilterClass ##### -->
+<!-- ##### MACRO GST_IDENTITY_CLASS ##### -->
<para>
</para>
+@klass:
-<!-- ##### MACRO GST_FDSINK ##### -->
+<!-- ##### MACRO GST_IS_ASYNCDISKSRC ##### -->
<para>
</para>
@obj:
-<!-- ##### FUNCTION gst_bin_schedule ##### -->
+<!-- ##### MACRO GST_IS_ASYNCDISKSRC_CLASS ##### -->
<para>
</para>
-@bin:
+@obj:
-<!-- ##### MACRO ERROR ##### -->
+<!-- ##### MACRO GST_IS_AUDIOSINK ##### -->
<para>
</para>
-@element:
-@format:
-@args...:
+@obj:
-<!-- ##### STRUCT MetaVideoRaw ##### -->
+<!-- ##### MACRO GST_IS_AUDIOSINK_CLASS ##### -->
<para>
</para>
-@meta:
-@format:
-@visual:
-@width:
-@height:
-@overlay_info:
-@dga_info:
+@obj:
-<!-- ##### FUNCTION gst_meta_ref ##### -->
+<!-- ##### MACRO GST_IS_AUDIOSRC ##### -->
<para>
</para>
-@meta:
+@obj:
-<!-- ##### SECTION ./tmpl/gstaudiosink.sgml:See_Also ##### -->
+<!-- ##### MACRO GST_IS_AUDIOSRC_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### MACRO GST_FILTER ##### -->
+<!-- ##### MACRO GST_IS_BIN ##### -->
<para>
</para>
@obj:
-<!-- ##### MACRO GST_DEBUG_LEAVE_STRING ##### -->
+<!-- ##### MACRO GST_IS_BIN_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### FUNCTION gst_esdsink_set_channels ##### -->
+<!-- ##### MACRO GST_IS_CONNECTION ##### -->
<para>
</para>
-@esdsink:
-@channels:
+@obj:
-<!-- ##### FUNCTION gst_autoplug_caps_list ##### -->
+<!-- ##### MACRO GST_IS_CONNECTION_CLASS ##### -->
<para>
</para>
-@autoplug:
-@srcpad:
-@sinkpad:
-@Varargs:
-@Returns:
-@srccaps:
-@sinkcaps:
+@obj:
-<!-- ##### MACRO GST_ELEMENT ##### -->
+<!-- ##### MACRO GST_IS_DISKSRC ##### -->
<para>
</para>
@obj:
-<!-- ##### ARG GstQueue:block ##### -->
+<!-- ##### MACRO GST_IS_DISKSRC_CLASS ##### -->
<para>
-Specify wether the queue blocks or not.
+
</para>
+@obj:
-<!-- ##### FUNCTION gst_pad_pull_region ##### -->
+<!-- ##### MACRO GST_IS_ELEMENT ##### -->
<para>
</para>
-@pad:
-@offset:
-@size:
-@Returns:
+@obj:
-<!-- ##### FUNCTION gst_fdsink_new_with_fd ##### -->
+<!-- ##### MACRO GST_IS_ELEMENT_CLASS ##### -->
<para>
</para>
-@name:
-@fd:
-@Returns:
+@obj:
-<!-- ##### MACRO GST_IS_ELEMENT_CLASS ##### -->
+<!-- ##### MACRO GST_IS_ESDSINK ##### -->
<para>
</para>
@obj:
-<!-- ##### STRUCT GstSrcClass ##### -->
+<!-- ##### MACRO GST_IS_ESDSINK_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### ARG GstIdentity:control ##### -->
+<!-- ##### MACRO GST_IS_FAKESINK ##### -->
<para>
</para>
+@obj:
-<!-- ##### TYPEDEF GstPropsListFactory[] ##### -->
+<!-- ##### MACRO GST_IS_FAKESINK_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### MACRO GST_PAD ##### -->
+<!-- ##### MACRO GST_IS_FAKESRC ##### -->
<para>
</para>
@obj:
-<!-- ##### FUNCTION gst_pad_set_pull_function ##### -->
+<!-- ##### MACRO GST_IS_FAKESRC_CLASS ##### -->
<para>
</para>
-@pad:
-@pull:
+@obj:
-<!-- ##### STRUCT GstSink ##### -->
+<!-- ##### MACRO GST_IS_FDSINK ##### -->
<para>
</para>
+@obj:
-<!-- ##### FUNCTION gst_pipeline_get_type ##### -->
+<!-- ##### MACRO GST_IS_FDSINK_CLASS ##### -->
<para>
</para>
-@Returns:
+@obj:
-<!-- ##### MACRO GST_IS_THREAD ##### -->
+<!-- ##### MACRO GST_IS_FDSRC ##### -->
<para>
</para>
@obj:
-<!-- ##### MACRO GST_TYPE_THREAD ##### -->
+<!-- ##### MACRO GST_IS_FDSRC_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### STRUCT GstAsyncDiskSrcClass ##### -->
+<!-- ##### MACRO GST_IS_FILTER ##### -->
<para>
</para>
+@obj:
-<!-- ##### FUNCTION gst_pad_set_caps_list ##### -->
+<!-- ##### MACRO GST_IS_FILTER_CLASS ##### -->
<para>
</para>
-@pad:
-@caps:
+@obj:
-<!-- ##### MACRO GST_PROPS_FOURCC_INT ##### -->
+<!-- ##### MACRO GST_IS_HTTPSRC ##### -->
<para>
-Create a fourcc property out of an integer value.
+
</para>
-@a: the integer value
+@obj:
-<!-- ##### MACRO GST_TYPE_SINK ##### -->
+<!-- ##### MACRO GST_IS_HTTPSRC_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### MACRO DEBUG_SET_STRING ##### -->
+<!-- ##### MACRO GST_IS_IDENTITY ##### -->
<para>
</para>
-@format:
-@args...:
+@obj:
-<!-- ##### MACRO GST_IS_THREAD_CLASS ##### -->
+<!-- ##### MACRO GST_IS_IDENTITY_CLASS ##### -->
<para>
</para>
@obj:
-<!-- ##### FUNCTION gst_bin_get_type ##### -->
+<!-- ##### MACRO GST_IS_OBJECT ##### -->
<para>
</para>
-@Returns:
+@obj:
-<!-- ##### ARG GstAsyncDiskSrc:offset ##### -->
+<!-- ##### MACRO GST_IS_OBJECT_CLASS ##### -->
<para>
-Specify the current offset in the file.
+
</para>
+@obj:
-<!-- ##### MACRO STACK_SIZE ##### -->
+<!-- ##### MACRO GST_IS_PAD ##### -->
<para>
</para>
+@obj:
-<!-- ##### MACRO GST_TYPE_AUDIOSINK ##### -->
+<!-- ##### MACRO GST_IS_PAD_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### SECTION ./tmpl/plugin.sgml:Long_Description ##### -->
+<!-- ##### MACRO GST_IS_PIPELINE ##### -->
<para>
</para>
+@obj:
-<!-- ##### MACRO GST_FILTER_CLASS ##### -->
+<!-- ##### MACRO GST_IS_PIPELINE_CLASS ##### -->
<para>
</para>
-@klass:
+@obj:
-<!-- ##### FUNCTION gst_pad_select ##### -->
+<!-- ##### MACRO GST_IS_QUEUE ##### -->
<para>
</para>
-@nextpad:
-@Varargs:
-@Returns:
+@obj:
-<!-- ##### FUNCTION gst_identity_get_type ##### -->
+<!-- ##### MACRO GST_IS_QUEUE_CLASS ##### -->
<para>
</para>
-@Returns:
+@obj:
-<!-- ##### TYPEDEF GstCapsFactory[] ##### -->
+<!-- ##### MACRO GST_IS_SINESRC ##### -->
<para>
</para>
+@obj:
-<!-- ##### MACRO GST_PROPS_BOOL_ID ##### -->
+<!-- ##### MACRO GST_IS_SINESRC_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### FUNCTION gst_meta_unref ##### -->
+<!-- ##### MACRO GST_IS_SINK ##### -->
<para>
</para>
-@meta:
+@obj:
-<!-- ##### STRUCT GstSineSrc ##### -->
+<!-- ##### MACRO GST_IS_SINK_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### STRUCT MetaDGA ##### -->
+<!-- ##### MACRO GST_IS_SRC ##### -->
<para>
</para>
-@base:
-@swidth:
-@sheight:
-@bytes_per_line:
-
-<!-- ##### SECTION ./tmpl/spectrum.sgml:Title ##### -->
-spectrum
-
+@obj:
-<!-- ##### SECTION ./tmpl/GstElement.sgml:Long_Description ##### -->
+<!-- ##### MACRO GST_IS_SRC_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### ARG GstAudioSink:format ##### -->
+<!-- ##### MACRO GST_IS_TEE ##### -->
<para>
</para>
+@obj:
-<!-- ##### MACRO GST_IS_FAKESINK_CLASS ##### -->
+<!-- ##### MACRO GST_IS_TEE_CLASS ##### -->
<para>
</para>
@obj:
-<!-- ##### MACRO GST_AUDIOSRC_CLASS ##### -->
+<!-- ##### MACRO GST_IS_THREAD ##### -->
<para>
</para>
-@klass:
+@obj:
-<!-- ##### STRUCT GstAudioSrcClass ##### -->
+<!-- ##### MACRO GST_IS_THREAD_CLASS ##### -->
<para>
</para>
+@obj:
-<!-- ##### FUNCTION gst_audiosrc_new ##### -->
+<!-- ##### MACRO GST_META ##### -->
<para>
</para>
-@name:
-@Returns:
+@meta:
-<!-- ##### STRUCT GstConnection ##### -->
+<!-- ##### MACRO GST_META_FLAGS ##### -->
<para>
-
+Retrieve the flags of the given meta information.
</para>
+@meta: the meta information
-<!-- ##### STRUCT GstQueueClass ##### -->
+<!-- ##### MACRO GST_META_FLAG_IS_SET ##### -->
<para>
-
+Check if a given flag is set.
</para>
+@meta: the meta data to test
+@flag: the flag to test
-<!-- ##### FUNCTION gst_fakesrc_push ##### -->
+<!-- ##### MACRO GST_META_FLAG_SET ##### -->
<para>
-
+Set a flag in the meta data.
</para>
-@src:
+@meta: the meta data
+@flag: the flag to set
-<!-- ##### FUNCTION gst_type_add_sink ##### -->
+<!-- ##### MACRO GST_META_FLAG_UNSET ##### -->
<para>
-
+Clear a flag in the meta data.
</para>
-@id:
-@sink:
+@meta: the meta data
+@flag: the flag to clear
-<!-- ##### MACRO GST_IS_IDENTITY_CLASS ##### -->
+<!-- ##### MACRO GST_OBJECT ##### -->
<para>
</para>
@obj:
-<!-- ##### SECTION ./tmpl/gstgetbits.sgml:Title ##### -->
-GstGetbits
-
-
-<!-- ##### SECTION ./tmpl/audioraw.sgml:Title ##### -->
-audioraw
-
-
-<!-- ##### MACRO GST_FDSINK_CLASS ##### -->
+<!-- ##### MACRO GST_OBJECT_CLASS ##### -->
<para>
</para>
@klass:
-<!-- ##### FUNCTION gst_fdsink_new ##### -->
+<!-- ##### MACRO GST_OBJECT_FLAG_LAST ##### -->
<para>
-
+subclasses can use this value to start the enumeration of their flags
</para>
-@name:
-@Returns:
-<!-- ##### FUNCTION gst_element_save_thyself ##### -->
+<!-- ##### MACRO GST_PAD ##### -->
<para>
</para>
-@element:
-@parent:
-@Returns:
+@obj:
-<!-- ##### MACRO GST_IS_TEE ##### -->
+<!-- ##### MACRO GST_PAD_CLASS ##### -->
<para>
</para>
-@obj:
+@klass:
-<!-- ##### FUNCTION gst_type_get_sink_to_src ##### -->
+<!-- ##### MACRO GST_PAD_FACTORY_ALWAYS ##### -->
<para>
-
+Indicate that this pad will always be available.
+Use this in the factory definition.
</para>
-@sinkid:
-@srcid:
-@Returns:
-<!-- ##### MACRO GST_PROPS_INT_ID ##### -->
+<!-- ##### MACRO GST_PAD_FACTORY_CAPS ##### -->
<para>
-
+Starts the declaration of a the capabilities for this padtemplate.
</para>
+@a...: a capability factory
-<!-- ##### STRUCT GstTeeClass ##### -->
+<!-- ##### MACRO GST_PAD_FACTORY_REQUEST ##### -->
<para>
-
+Indicates that this pad will be available on request. Use
+this in the factory definition.
</para>
-<!-- ##### MACRO GST_FAKESINK ##### -->
+<!-- ##### MACRO GST_PAD_FACTORY_SINK ##### -->
<para>
-
+Indicates a sinkpad for the padfactory.
</para>
-@obj:
-<!-- ##### FUNCTION gst_type_get_srcs ##### -->
+<!-- ##### MACRO GST_PAD_FACTORY_SOMETIMES ##### -->
<para>
-
+Indicate that this pad will become available depending
+on the media type. Use this in the factory definition.
</para>
-@id:
-@Returns:
-<!-- ##### FUNCTION gst_esdsink_set_frequency ##### -->
+<!-- ##### MACRO GST_PAD_FACTORY_SRC ##### -->
<para>
-
+Indicates a srcpad for the padfactory.
</para>
-@esdsink:
-@frequency:
-<!-- ##### SECTION ./tmpl/gstgetbits.sgml:Short_Description ##### -->
+<!-- ##### MACRO GST_PIPELINE ##### -->
+<para>
+</para>
+@obj:
-<!-- ##### MACRO GST_TYPE_SRC ##### -->
+<!-- ##### MACRO GST_PIPELINE_CLASS ##### -->
<para>
</para>
+@klass:
-<!-- ##### MACRO GST_FAKESRC ##### -->
+<!-- ##### MACRO GST_PROPS_BOOL_ID ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_IS_HTTPSRC ##### -->
+<!-- ##### MACRO GST_PROPS_FLOAT_RANGE_STRING ##### -->
<para>
</para>
-@obj:
+@a:
+@b:
-<!-- ##### MACRO GST_DEBUG_NOPREFIX ##### -->
+<!-- ##### MACRO GST_PROPS_FLOAT_STRING ##### -->
<para>
</para>
-@cat:
-@format:
-@args...:
+@a:
-<!-- ##### MACRO GST_IDENTITY ##### -->
+<!-- ##### MACRO GST_PROPS_FOURCC_ID ##### -->
<para>
</para>
-@obj:
-<!-- ##### ARG GstAudioSrc:format ##### -->
+<!-- ##### MACRO GST_PROPS_FOURCC_INT ##### -->
<para>
-The audio format as defined in soundcard.h
+Create a fourcc property out of an integer value.
</para>
+@a: the integer value
-<!-- ##### MACRO GST_IS_HTTPSRC_CLASS ##### -->
+<!-- ##### MACRO GST_PROPS_INT_ID ##### -->
<para>
</para>
-@obj:
-
-<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:Title ##### -->
-GstAsyncDiskSrc
-
-<!-- ##### MACRO GST_TYPE_ASYNCDISKSRC ##### -->
->>>>>>> 1.23.2.3
+<!-- ##### MACRO GST_PROPS_INT_RANGE_ID ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_elementfactory_add_sink ##### -->
+<!-- ##### MACRO GST_PROPS_LIST_ID ##### -->
<para>
</para>
-@elementfactory:
-@id:
-<!-- ##### FUNCTION gst_bin_schedule_func ##### -->
+<!-- ##### MACRO GST_QUEUE ##### -->
<para>
</para>
-@bin:
+@obj:
-<!-- ##### MACRO GST_IS_OBJECT ##### -->
+<!-- ##### MACRO GST_QUEUE_CLASS ##### -->
<para>
</para>
-@obj:
+@klass:
-<!-- ##### MACRO GST_TYPE_OBJECT ##### -->
+<!-- ##### MACRO GST_RPAD_EOSFUNC ##### -->
<para>
-
+Get the EOS function of the real pad.
</para>
+@pad: the real pad to query.
-<!-- ##### ARG GstSineSrc:frequency ##### -->
+<!-- ##### MACRO GST_RPAD_PULLFUNC ##### -->
<para>
-The fequency.
+Get the pullfunction of the real pad.
</para>
+@pad: the real pad to query.
-<!-- ##### FUNCTION gst_src_get_type ##### -->
+<!-- ##### MACRO GST_RPAD_PUSHFUNC ##### -->
<para>
+Get the pushfunction of the real pad.
+</para>
+@pad: the real pad to query.
+
+<!-- ##### MACRO GST_RPAD_QOSFUNC ##### -->
+<para>
+Get the QoS function of the real pad.
</para>
-@Returns:
+@pad: the real pad to query.
-<!-- ##### FUNCTION gst_tee_new ##### -->
+<!-- ##### MACRO GST_SINESRC ##### -->
<para>
</para>
-@name:
-@Returns:
+@obj:
-<!-- ##### STRUCT GstAudioSink ##### -->
+<!-- ##### MACRO GST_SINESRC_CLASS ##### -->
<para>
</para>
+@klass:
-<!-- ##### MACRO GST_IS_QUEUE ##### -->
+<!-- ##### MACRO GST_SINK ##### -->
<para>
</para>
@obj:
-<!-- ##### TYPEDEF GstPropsFactory[] ##### -->
+<!-- ##### MACRO GST_SINK_CLASS ##### -->
<para>
</para>
+@klass:
-<!-- ##### SIGNAL GstAudioSink::handoff ##### -->
+<!-- ##### MACRO GST_SINK_FLAG_LAST ##### -->
<para>
-The buffer is sent to the sound card.
+
</para>
-@gstaudiosink: the object which received the signal.
-@arg1: the audiosink.
-<!-- ##### MACRO GST_IS_FDSRC_CLASS ##### -->
+<!-- ##### MACRO GST_SRC ##### -->
<para>
</para>
@obj:
-<!-- ##### MACRO GST_IS_OBJECT_CLASS ##### -->
+<!-- ##### MACRO GST_SRC_ASYNC ##### -->
<para>
-
+This macro checks to see if the GST_SRC_ASYNC flag is set.
</para>
-@obj:
+@obj: GstSrc to check for flag in.
-<!-- ##### FUNCTION gst_esdsink_chain ##### -->
+<!-- ##### MACRO GST_SRC_CLASS ##### -->
<para>
</para>
-@pad:
-@buf:
+@klass:
-<!-- ##### FUNCTION gst_buffer_add_meta ##### -->
+<!-- ##### MACRO GST_SRC_FLAGS ##### -->
<para>
-
+This macro returns the entire set of flags for the object.
</para>
-@buffer:
-@meta:
+@obj: GstSrc to return flags for.
-<!-- ##### FUNCTION gst_elementfactory_can_src_caps_list ##### -->
+<!-- ##### MACRO GST_SRC_IS_ASYNC ##### -->
<para>
-
+Query a GstSrc for the ASYNC flag
</para>
-@factory:
-@caps:
-@Returns:
+@obj: The GstSrc to query
-<!-- ##### FUNCTION gst_queue_chain ##### -->
+<!-- ##### MACRO GST_SRC_SET_FLAGS ##### -->
<para>
-
+This macro sets the given flags.
</para>
-@pad:
-@buf:
+@src:
+@flag: Flag to set, can by any number of bits in guint32.
+@obj: GstSrc to set flag in.
-<!-- ##### MACRO GST_TYPE_QUEUE ##### -->
+<!-- ##### MACRO GST_SRC_UNSET_FLAGS ##### -->
<para>
-
+This macro usets the given flags.
</para>
+@src:
+@flag: Flag to set, must be a single bit in guint32.
+@obj: GstSrc to unset flag in.
-<!-- ##### FUNCTION gst_buffer_remove_meta ##### -->
+<!-- ##### MACRO GST_STATE_IS_SET ##### -->
<para>
-
+This macro checks to see if the given state is set.
</para>
-@buffer:
-@meta:
+@obj: Element to check for state.
+@flag: State to check for, must be a single bit in guint32.
-<!-- ##### FUNCTION gst_caps_register_count ##### -->
+<!-- ##### MACRO GST_STATE_PLAYING_TO_READY ##### -->
<para>
-
+The Element is going from the PLAYING state to the READY state.
</para>
-@factory:
-@counter:
-@Returns:
-@count:
-<!-- ##### MACRO GST_TYPE_HTTPSRC ##### -->
+<!-- ##### MACRO GST_STATE_READY_TO_PLAYING ##### -->
<para>
-
+The Element is going from the READY state to the PLAYING state.
</para>
-<!-- ##### MACRO GST_TYPE_PAD ##### -->
+<!-- ##### MACRO GST_STATE_SET ##### -->
<para>
-
+This macro sets the given state on the element.
</para>
+@obj: Element to set state of.
+@flag: State to set, can be any number of bits in guint32.
-<!-- ##### MACRO GST_IS_AUDIOSRC ##### -->
+<!-- ##### MACRO GST_STATE_UNSET ##### -->
<para>
-
+This macro unsets the given state on the element.
</para>
-@obj:
+@obj: Element to unset state of.
+@flag: State to unset, can be any number of bits in guint32.
-<!-- ##### MACRO GST_DISKSRC ##### -->
+<!-- ##### MACRO GST_TEE ##### -->
<para>
</para>
@obj:
-<!-- ##### MACRO INFO_ELEMENT ##### -->
+<!-- ##### MACRO GST_TEE_CLASS ##### -->
<para>
</para>
-@cat:
-@element:
-@format:
-@args...:
+@klass:
-<!-- ##### MACRO GST_SINK_CLASS ##### -->
+<!-- ##### MACRO GST_THREAD ##### -->
<para>
</para>
-@klass:
+@obj:
-<!-- ##### STRUCT GstAudioSinkClass ##### -->
+<!-- ##### MACRO GST_THREAD_CLASS ##### -->
<para>
</para>
+@klass:
-<!-- ##### FUNCTION gst_type_add_src ##### -->
+<!-- ##### MACRO GST_TYPE_ASYNCDISKSRC ##### -->
+>>>>>>> 1.23.2.3
<para>
</para>
-@id:
-@src:
-<!-- ##### STRUCT GstFdSink ##### -->
+<!-- ##### MACRO GST_TYPE_AUDIOSINK ##### -->
<para>
</para>
-<!-- ##### MACRO GST_IS_PIPELINE ##### -->
+<!-- ##### MACRO GST_TYPE_AUDIOSRC ##### -->
<para>
</para>
-@obj:
-<!-- ##### STRUCT GstFdSinkClass ##### -->
+<!-- ##### MACRO GST_TYPE_BIN ##### -->
<para>
</para>
-<!-- ##### MACRO GST_IS_SINESRC_CLASS ##### -->
+<!-- ##### MACRO GST_TYPE_CONNECTION ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_ASYNCDISKSRC_CLASS ##### -->
+<!-- ##### MACRO GST_TYPE_DISKSRC ##### -->
<para>
</para>
-@klass:
-<!-- ##### FUNCTION gst_esdsink_sync_parms ##### -->
+<!-- ##### MACRO GST_TYPE_ELEMENT ##### -->
<para>
</para>
-@esdsink:
-<!-- ##### FUNCTION gst_connection_push ##### -->
+<!-- ##### MACRO GST_TYPE_ESDSINK ##### -->
<para>
</para>
-@connection:
-<!-- ##### SIGNAL GstDiskSink::handoff ##### -->
+<!-- ##### MACRO GST_TYPE_FAKESINK ##### -->
<para>
-Is emited after the buffer has been written to the disk.
+
</para>
-@gstdisksink: the object which received the signal.
-<!-- ##### FUNCTION gst_audiosink_new ##### -->
+<!-- ##### MACRO GST_TYPE_FAKESRC ##### -->
<para>
</para>
-@name:
-@Returns:
-<!-- ##### FUNCTION gst_bin_set_element_manager ##### -->
+<!-- ##### MACRO GST_TYPE_FDSINK ##### -->
<para>
</para>
-@element:
-@manager:
-<!-- ##### MACRO GST_ESDSINK ##### -->
+<!-- ##### MACRO GST_TYPE_FDSRC ##### -->
<para>
</para>
-@obj:
-<!-- ##### FUNCTION gst_type_initialize ##### -->
+<!-- ##### MACRO GST_TYPE_FILTER ##### -->
<para>
</para>
-<!-- ##### SECTION ./tmpl/gstfilter.sgml:Title ##### -->
-GstFilter
-
-
-<!-- ##### MACRO GST_TEE ##### -->
+<!-- ##### MACRO GST_TYPE_HTTPSRC ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_IS_QUEUE_CLASS ##### -->
+<!-- ##### MACRO GST_TYPE_IDENTITY ##### -->
<para>
</para>
-@obj:
-<!-- ##### FUNCTION gst_fdsrc_get_type ##### -->
+<!-- ##### MACRO GST_TYPE_OBJECT ##### -->
<para>
</para>
-@Returns:
-<!-- ##### FUNCTION gst_pad_get_type_id ##### -->
+<!-- ##### MACRO GST_TYPE_PAD ##### -->
<para>
</para>
-@pad:
-@Returns:
-<!-- ##### FUNCTION gst_thread_iterate ##### -->
+<!-- ##### MACRO GST_TYPE_PIPELINE ##### -->
<para>
</para>
-@thread:
-<!-- ##### STRUCT OverlayClip ##### -->
+<!-- ##### MACRO GST_TYPE_QUEUE ##### -->
<para>
</para>
-@x1:
-@x2:
-@y1:
-@y2:
-<!-- ##### ENUM GstSrcFlags ##### -->
+<!-- ##### MACRO GST_TYPE_SINESRC ##### -->
<para>
-Flags for the GstSrc element
-</para>
-
-@GST_SRC_ASYNC: Indicates that this src is asynchronous
-@GST_SRC_FLAG_LAST: subclasses can use this to number their flags
-
-<!-- ##### SECTION ./tmpl/gstaudiosink.sgml:Short_Description ##### -->
+</para>
-<!-- ##### SECTION ./tmpl/gstcolorspace.sgml:Title ##### -->
-GstColorSpace
-
-
-<!-- ##### TYPEDEF GstPadFactoryEntry ##### -->
+<!-- ##### MACRO GST_TYPE_SINK ##### -->
<para>
-Defines an entry for a padfactory.
+
</para>
-<!-- ##### ENUM GstAsyncDiskSrcFlags ##### -->
+<!-- ##### MACRO GST_TYPE_SRC ##### -->
<para>
-<informaltable pgwide=1 frame="none" role="enum">
-<tgroup cols="2"><colspec colwidth="2*"><colspec colwidth="8*">
-<tbody>
-<row>
-<entry>GST_ASYNCDISKSRC_OPEN</entry>
-<entry>the asyncdisksrc is open for reading</entry>
-</row>
-
-</tbody></tgroup></informaltable>
</para>
-@GST_ASYNCDISKSRC_OPEN:
-@GST_ASYNCDISKSRC_FLAG_LAST:
-<!-- ##### STRUCT GstAsyncDiskSrc ##### -->
+<!-- ##### MACRO GST_TYPE_TEE ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_element_change_state ##### -->
+<!-- ##### MACRO GST_TYPE_THREAD ##### -->
<para>
</para>
-@element:
-@state:
-@Returns:
-<!-- ##### FUNCTION gst_pad_get_ghost_parents ##### -->
+<!-- ##### STRUCT GstAsyncDiskSrc ##### -->
<para>
</para>
-@pad:
-@Returns:
-<!-- ##### STRUCT GstFilter ##### -->
+<!-- ##### ARG GstAsyncDiskSrc:bytesperread ##### -->
<para>
-
+Specify how many bytes to read at a time.
</para>
-<!-- ##### MACRO GST_IS_BIN ##### -->
+<!-- ##### ARG GstAsyncDiskSrc:length ##### -->
<para>
-
+Get the size of the current file.
</para>
-@obj:
-<!-- ##### MACRO GST_OBJECT_FLAG_LAST ##### -->
+<!-- ##### ARG GstAsyncDiskSrc:location ##### -->
<para>
-subclasses can use this value to start the enumeration of their flags
+Specify the location of the file to read.
</para>
-<!-- ##### SECTION ./tmpl/spectrum.sgml:Short_Description ##### -->
-Frequencies of a spectrum analysis.
+<!-- ##### ARG GstAsyncDiskSrc:offset ##### -->
+<para>
+Specify the current offset in the file.
+</para>
-<!-- ##### FUNCTION gst_asyncdisksrc_get_type ##### -->
+<!-- ##### ARG GstAsyncDiskSrc:size ##### -->
<para>
</para>
-@Returns:
-<!-- ##### MACRO GST_AUDIOSINK_CLASS ##### -->
+<!-- ##### STRUCT GstAsyncDiskSrcClass ##### -->
<para>
</para>
-@klass:
-<!-- ##### MACRO GST_PAD_FACTORY_SINK ##### -->
+<!-- ##### ENUM GstAsyncDiskSrcFlags ##### -->
<para>
-Indicates a sinkpad for the padfactory.
-</para>
-
+<informaltable pgwide=1 frame="none" role="enum">
+<tgroup cols="2"><colspec colwidth="2*"><colspec colwidth="8*">
+<tbody>
+<row>
+<entry>GST_ASYNCDISKSRC_OPEN</entry>
+<entry>the asyncdisksrc is open for reading</entry>
+</row>
-<!-- ##### MACRO GST_SRC_CLASS ##### -->
-<para>
+</tbody></tgroup></informaltable>
</para>
-@klass:
+@GST_ASYNCDISKSRC_OPEN:
+@GST_ASYNCDISKSRC_FLAG_LAST:
-<!-- ##### SECTION ./tmpl/gstcolorspace.sgml:Long_Description ##### -->
+<!-- ##### STRUCT GstAudioSink ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_type_load_thyself ##### -->
+<!-- ##### SIGNAL GstAudioSink::handoff ##### -->
<para>
-
+The buffer is sent to the sound card.
</para>
-@parent:
-@Returns:
+@gstaudiosink: the object which received the signal.
+@arg1: the audiosink.
-<!-- ##### FUNCTION gst_pad_get_caps_list ##### -->
+<!-- ##### ARG GstAudioSink:channels ##### -->
<para>
</para>
-@pad:
-@Returns:
-<!-- ##### MACRO GST_PROPS_FOURCC_ID ##### -->
+<!-- ##### ARG GstAudioSink:format ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_esdsink_new ##### -->
+<!-- ##### ARG GstAudioSink:frequency ##### -->
<para>
</para>
-@name:
-@Returns:
-<!-- ##### MACRO GST_META_FLAGS ##### -->
+<!-- ##### ARG GstAudioSink:mute ##### -->
<para>
-Retrieve the flags of the given meta information.
+
</para>
-@meta: the meta information
-<!-- ##### FUNCTION gst_element_request_pad ##### -->
+<!-- ##### STRUCT GstAudioSinkClass ##### -->
<para>
</para>
-@element:
-@templ:
-@Returns:
-@temp:
-<!-- ##### MACRO GST_SINESRC ##### -->
+<!-- ##### STRUCT GstAudioSrc ##### -->
<para>
</para>
-@obj:
-
-<!-- ##### SECTION ./tmpl/gstsink.sgml:Short_Description ##### -->
-The end point of a filter graph
-
-<!-- ##### STRUCT MetaAudioRaw ##### -->
+<!-- ##### ARG GstAudioSrc:bytes-per-read ##### -->
<para>
-
+The number of bytes per read.
</para>
-@meta:
-@format:
-@channels:
-@frequency:
-@bps:
<!-- ##### ARG GstAudioSrc:channels ##### -->
<para>
</para>
-<!-- ##### STRUCT GstFakeSink ##### -->
+<!-- ##### ARG GstAudioSrc:curoffset ##### -->
<para>
-
+Get the current number of bytes read.
</para>
-<!-- ##### MACRO GST_STATE_IS_SET ##### -->
+<!-- ##### ARG GstAudioSrc:format ##### -->
<para>
-This macro checks to see if the given state is set.
+The audio format as defined in soundcard.h
</para>
-@obj: Element to check for state.
-@flag: State to check for, must be a single bit in guint32.
-<!-- ##### STRUCT GstMeta ##### -->
+<!-- ##### ARG GstAudioSrc:frequency ##### -->
<para>
-
+The frequency.
</para>
-@lock: for locking purposes
-@flags: the flags of the meta data
-@data: the meta data
-@size: the size of the meta data
-<!-- ##### FUNCTION gst_xml_new_from_memory ##### -->
+<!-- ##### STRUCT GstAudioSrcClass ##### -->
<para>
</para>
-@buffer:
-@size:
-@root:
-@Returns:
-<!-- ##### MACRO GST_PROPS_LIST_ID ##### -->
+<!-- ##### STRUCT GstBinClass ##### -->
<para>
</para>
-<!-- ##### SECTION ./tmpl/gstconnection.sgml:See_Also ##### -->
+<!-- ##### USER_FUNCTION GstBufferPoolCreateFunction ##### -->
<para>
-
+The function called when a buffer has to be created for this pool.
</para>
+@pool: the pool from which to create the buffer
+@user_data: any user data
+@Returns: a new buffer from the pool
-<!-- ##### FUNCTION plugin_load ##### -->
+<!-- ##### USER_FUNCTION GstBufferPoolDestroyFunction ##### -->
<para>
-
+This function will be called when the given buffer has to be returned to
+the pool.
</para>
-@name:
-@Returns:
+@pool: the pool to return the buffer to
+@buffer: the buffer to return
+@user_data: any user data
-<!-- ##### MACRO GST_IS_ELEMENT ##### -->
+<!-- ##### ENUM GstCapsDefinition ##### -->
<para>
</para>
-@obj:
-
-<!-- ##### SECTION ./tmpl/gstaudiosink.sgml:Title ##### -->
-GstAudioSink
-
+@GST_CAPS_ALWAYS:
+@GST_CAPS_MAYBE:
-<!-- ##### MACRO GST_IS_ASYNCDISKSRC ##### -->
+<!-- ##### TYPEDEF GstCapsFactory ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_SRC_SET_FLAGS ##### -->
+<!-- ##### TYPEDEF GstCapsFactoryEntry ##### -->
<para>
-This macro sets the given flags.
-</para>
-
-@src:
-@flag: Flag to set, can by any number of bits in guint32.
-@obj: GstSrc to set flag in.
-<!-- ##### MACRO GST_BUFFER_TYPE ##### -->
-<para>
-Retrieves the type id of the data in the buffer.
</para>
-@buf: GstBuffer
-<!-- ##### MACRO GST_PROPS_FLOAT_STRING ##### -->
+<!-- ##### TYPEDEF GstCapsFactory[] ##### -->
<para>
</para>
-@a:
-<!-- ##### MACRO DEBUG_LEAVE_STRING ##### -->
+<!-- ##### STRUCT GstConnection ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_filter_get_type ##### -->
+<!-- ##### STRUCT GstConnectionClass ##### -->
<para>
</para>
-@Returns:
-<!-- ##### FUNCTION plugin_load_absolute ##### -->
+<!-- ##### SIGNAL GstDiskSink::handoff ##### -->
<para>
-
+Is emited after the buffer has been written to the disk.
</para>
-@name:
-@Returns:
+@gstdisksink: the object which received the signal.
-<!-- ##### STRUCT GstObjectClass ##### -->
+<!-- ##### ARG GstDiskSink:closed ##### -->
<para>
</para>
-<!-- ##### SECTION ./tmpl/gstsink.sgml:Title ##### -->
-GstSink
-
-
-<!-- ##### MACRO GST_CPU_FLAG_MMX ##### -->
+<!-- ##### ARG GstDiskSink:location ##### -->
<para>
-A flag indicating that MMX instructions are supported.
+The filename to write to.
</para>
-<!-- ##### FUNCTION gst_object_get_type ##### -->
+<!-- ##### STRUCT GstDiskSrc ##### -->
<para>
</para>
-@Returns:
-<!-- ##### STRUCT GstSineSrcClass ##### -->
+<!-- ##### ARG GstDiskSrc:size ##### -->
<para>
-
+Get the size of the file.
</para>
-<!-- ##### FUNCTION gst_elementfactory_can_sink_caps_list ##### -->
+<!-- ##### STRUCT GstDiskSrcClass ##### -->
<para>
</para>
-@factory:
-@caps:
-@Returns:
-<!-- ##### MACRO GST_SRC_UNSET_FLAGS ##### -->
+<!-- ##### STRUCT GstElementClass ##### -->
<para>
-This macro usets the given flags.
+
</para>
-@src:
-@flag: Flag to set, must be a single bit in guint32.
-@obj: GstSrc to unset flag in.
-<!-- ##### ARG GstAudioSrc:frequency ##### -->
+<!-- ##### STRUCT GstEsdSink ##### -->
<para>
-The frequency.
+
</para>
-<!-- ##### MACRO GST_PAD_FACTORY_SRC ##### -->
+<!-- ##### STRUCT GstEsdSinkClass ##### -->
<para>
-Indicates a srcpad for the padfactory.
+
</para>
-<!-- ##### ARG GstDiskSink:closed ##### -->
+<!-- ##### STRUCT GstFakeSink ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_buffer_get_first_meta ##### -->
+<!-- ##### ARG GstFakeSink:num-sources ##### -->
<para>
</para>
-@buffer:
-@Returns:
-<!-- ##### MACRO GST_IS_SINK_CLASS ##### -->
+<!-- ##### STRUCT GstFakeSinkClass ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_IS_PIPELINE_CLASS ##### -->
+<!-- ##### STRUCT GstFakeSrc ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_PROPS_INT_RANGE_ID ##### -->
+<!-- ##### ARG GstFakeSrc:patern ##### -->
<para>
</para>
-<!-- ##### STRUCT GstAudioSrc ##### -->
+<!-- ##### STRUCT GstFakeSrcClass ##### -->
<para>
</para>
-<!-- ##### MACRO GST_TYPE_ELEMENT ##### -->
+<!-- ##### STRUCT GstFdSink ##### -->
<para>
</para>
-<!-- ##### ARG GstFakeSrc:patern ##### -->
+<!-- ##### STRUCT GstFdSinkClass ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_pad_get_caps_by_name ##### -->
+<!-- ##### STRUCT GstFdSrc ##### -->
<para>
</para>
-@pad:
-@name:
-@Returns:
-<!-- ##### SECTION ./tmpl/gstsrc.sgml:See_Also ##### -->
+<!-- ##### STRUCT GstFdSrcClass ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_esdsink_set_format ##### -->
+<!-- ##### STRUCT GstFilter ##### -->
<para>
</para>
-@esdsink:
-@format:
-<!-- ##### MACRO GST_DEBUG_PREFIX ##### -->
+<!-- ##### STRUCT GstFilterClass ##### -->
<para>
</para>
-@cat:
-@format:
-@args...:
-<!-- ##### SECTION ./tmpl/gstcolorspace.sgml:See_Also ##### -->
+<!-- ##### STRUCT GstHttpSrc ##### -->
<para>
</para>
-<!-- ##### MACRO GST_IS_FDSRC ##### -->
+<!-- ##### STRUCT GstHttpSrcClass ##### -->
<para>
</para>
-@obj:
<!-- ##### STRUCT GstIdentity ##### -->
<para>
</para>
-<!-- ##### FUNCTION gst_thread_get_type ##### -->
+<!-- ##### ARG GstIdentity:control ##### -->
<para>
</para>
-@Returns:
-<!-- ##### MACRO GST_QUEUE ##### -->
+<!-- ##### STRUCT GstIdentityClass ##### -->
<para>
</para>
-@obj:
-<!-- ##### MACRO GST_THREAD ##### -->
+<!-- ##### STRUCT GstMeta ##### -->
<para>
</para>
-@obj:
+@lock: for locking purposes
+@flags: the flags of the meta data
+@data: the meta data
+@size: the size of the meta data
-<!-- ##### MACRO COTHREAD_MAXTHREADS ##### -->
+<!-- ##### ENUM GstMetaFlags ##### -->
<para>
-The maximum number of cothreads we are going to support.
+Flags indicating properties about the meta data.
</para>
+@GST_META_FREEABLE: the meta data can be freed
-<!-- ##### FUNCTION gst_fakesink_new ##### -->
+<!-- ##### STRUCT GstObjectClass ##### -->
<para>
</para>
-@name:
-@Returns:
-<!-- ##### MACRO GST_PAD_FACTORY_CAPS ##### -->
+<!-- ##### ARG GstPad:active ##### -->
<para>
-Starts the declaration of a the capabilities for this padtemplate.
+Indicates this pad is active
</para>
-@a...: a capability factory
-
-<!-- ##### SECTION ./tmpl/gstsrc.sgml:Title ##### -->
-GstSrc
-
-<!-- ##### FUNCTION gst_pad_get_directory ##### -->
+<!-- ##### STRUCT GstPadClass ##### -->
<para>
</para>
-@pad:
-@Returns:
-
-<!-- ##### FUNCTION gst_tee_chain ##### -->
-<para>
-</para>
+<<<<<<< gstreamer-unused.sgml
-@pad:
-@buf:
-<!-- ##### FUNCTION gst_caps_new_with_props ##### -->
+<!-- ##### USER_FUNCTION GstPadEOSFunction ##### -->
<para>
-
+The function that will be called in an EOS case.
</para>
-@name:
-@mime:
-@props:
-@Returns:
+@pad: the pad that needs to be set to EOS state
+@Returns: TRUE if EOS was successful, FALSE otherwise
-<!-- ##### MACRO GST_STATE_READY_TO_PLAYING ##### -->
+<!-- ##### TYPEDEF GstPadFactoryEntry ##### -->
<para>
-The Element is going from the READY state to the PLAYING state.
+Defines an entry for a padfactory.
</para>
-<!-- ##### MACRO GST_TYPE_AUDIOSRC ##### -->
+<!-- ##### TYPEDEF GstPadFactory[] ##### -->
<para>
-
+The padfactory.
</para>
-<!-- ##### SECTION ./tmpl/plugin.sgml:See_Also ##### -->
+<!-- ##### USER_FUNCTION GstPadPullFunction ##### -->
<para>
-
+The function that will be called when pulling buffers.
</para>
+@pad: the pad to pull
+@Returns: a GstBuffer
-<!-- ##### SECTION ./tmpl/gstmeta.sgml:See_Also ##### -->
+<!-- ##### USER_FUNCTION GstPadPushFunction ##### -->
<para>
+The function that will be called when pushing a buffers.
</para>
+@pad: the pad to push
+@buf: a GstBuffer to push
-<!-- ##### MACRO GST_IS_TEE_CLASS ##### -->
+<!-- ##### USER_FUNCTION GstPadQoSFunction ##### -->
<para>
-
+The function that will be called when a QoS message is sent.
</para>
-@obj:
+@pad: the pad that sent the QoS message
+@qos_message: the message
-<!-- ##### FUNCTION gst_thread_main_loop ##### -->
+<!-- ##### STRUCT GstPipelineClass ##### -->
<para>
</para>
-@arg:
-<!-- ##### SECTION ./tmpl/gstmeta.sgml:Long_Description ##### -->
+<!-- ##### STRUCT GstPluginElement ##### -->
<para>
-The point of the metadata is to provide some context for each buffer. In
-the case of audio data, for instance, it would provide the samplerate, bit
-depth, and channel count.
-</para>
-<para>
-The trick is that there may be multiple types of metadata ganged onto a
-single buffer. This is why they're going to be a GList. This does mean
-extra overhead in all cases, but I think it's minimal. The GList type
-uses a chunk allocater so we're not wasting too much memory or time when
-adding to the list.
</para>
-<para>
-The trick is dealing with these structs as they pass through a pipeline,
-since they have potentially different mutability properties. For
-instance, if you've got a mp3 decoder connected to a tee, which sends the
-buffers off to both the decoder and a spectrum analyzer (and then a
-visualization element). The preferred setup would be where every time a
-audio/raw metadata comes down the pipe (indicating a potential change in
-audio format), the audiosink and spectrum would just save off pointers.
-</para>
+<!-- ##### TYPEDEF GstPropsFactoryEntry ##### -->
<para>
-So when exactly does this metadata go away (deallocated)? Well, that
-means metadata has to be refcounted. But that gets rather hairy. OK, in
-the simple case you create a metadata struct, it comes with refcount set
-to 1. You pass it through, it stays one, eventually someone drops the
-last reference on the buffer it's tied to, you free the metadata too.
-Easy. What if you tee? You could go through and for every metadata in
-the buffer, increment the refcount by the same as the buffer. So in the
-above case (tee'd), the audiosink and spectrum would get the buffer with a
-refcount of 2, and it'd have a metadata with refcount 2. Do they ref it
-each themselves, then unref the buffer? Or do they remove the metadata?
-Removing the metadata would require a buffer CoW, which would suck, so
-yes, they'd just ref the metadata.
-</para>
-<para>
-But.... what if they're all in different threads? Then we're off into
-the magical world of mutexes. Everything with a refcount in a threaded
-world must be mutexed, else you can do atomic increment and atomic
-dec and test. Can this be done from C easily? Perhaps it needs to be found
-from kernel includes via autoconf?
</para>
-<para>
-The goal in designing the way metadata will be defined and used is to keep
-it as simple as possible. The basis for accomplishing this is the fact
-that in order to actually use (rather than just pass) the metadata, you
-have to know what the fields are, which means you have to have compiled in
-support for that metadata at build time. Therefore, if you're using
-metadata, you must have build-time access to the necessary include file
-that defines it.
-</para>
+<!-- ##### TYPEDEF GstPropsFactory[] ##### -->
<para>
-So, given that you've got an include file, it would be nice if the whole
-thing could be contained there. This would limit the need to be linked
-against something, or have load-time requirements as to that has to be
-loaded before you are.
-</para>
-<para>
-Given that really all metadata is is a region of memory of a given size
-with a certain signature, this isn't all that hard. First you lay out the
-struct that defines the metadata. Then you set up #defines that expand to
-the size of the struct in question, as well as the four-cc code that
-defines the type.
</para>
-<para>
-The work is done by a few #defines, a la the #defines used in all Gtk
-objects. The first is a NEW() method that allocates the memory for the
-metadata and fills in all the normal fields (type, size, utility
-functions). Because of the way it's defined (as a #define, no less),
-you'll have to invoke it as META_NEW(meta), since it can't return()
-anything.
-</para>
+<!-- ##### ENUM GstPropsId ##### -->
<para>
-Another #define will check to make sure a meta is indeed that type by
-verifying the type code and size. Theoretically, meta types can overlap
-with the same fourcc code, as long as they have different sizes. But I
-probably ought to have a global public registry so people writing things
-don't conflict. MSFT got that right, at least.
-</para>
-<para>
-So, a hairy problem is what to do when there are utility functions
-associated with one of these things. One option is to not bother with
-them. This is very likely a possible solution, since metadata is supposed
-to be flat memory of a given size. Not much to do to either free or copy
-it, is there?
</para>
+@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:
-<!-- ##### SECTION ./tmpl/gstconnection.sgml:Title ##### -->
-GstConnection
-
-
-<!-- ##### MACRO GST_TYPE_FDSRC ##### -->
+<!-- ##### TYPEDEF GstPropsListFactory[] ##### -->
<para>
</para>
-<!-- ##### MACRO GST_TYPE_PIPELINE ##### -->
+<!-- ##### STRUCT GstQueue ##### -->
<para>
</para>
-<!-- ##### STRUCT GstHttpSrcClass ##### -->
+<!-- ##### ARG GstQueue:block ##### -->
<para>
-
+Specify wether the queue blocks or not.
</para>
-<!-- ##### SECTION ./tmpl/GstElement.sgml:Short_Description ##### -->
+<!-- ##### ARG GstQueue:timeout ##### -->
+<para>
+</para>
-<!-- ##### SECTION ./tmpl/gstesdsink.sgml:See_Also ##### -->
+<!-- ##### STRUCT GstQueueClass ##### -->
<para>
</para>
-<!-- ##### MACRO GST_TYPE_TEE ##### -->
+<!-- ##### STRUCT GstSineSrc ##### -->
<para>
</para>
-<!-- ##### MACRO GST_BIN ##### -->
+<!-- ##### ARG GstSineSrc:channels ##### -->
<para>
-
+The number of channels.
</para>
-@obj:
-<!-- ##### SECTION ./tmpl/GstElement.sgml:Title ##### -->
-GstElement
+<!-- ##### ARG GstSineSrc:frequency ##### -->
+<para>
+The fequency.
+</para>
-<!-- ##### FUNCTION gst_type_get_sinks ##### -->
+<!-- ##### STRUCT GstSineSrcClass ##### -->
<para>
</para>
-@id:
-@Returns:
-<!-- ##### MACRO GST_BUFFER_POOL ##### -->
+<!-- ##### STRUCT GstSink ##### -->
<para>
</para>
-@buf:
-<!-- ##### STRUCT GstEsdSink ##### -->
+<!-- ##### STRUCT GstSinkClass ##### -->
<para>
</para>
-<!-- ##### MACRO GST_META_FLAG_UNSET ##### -->
+<!-- ##### STRUCT GstSrc ##### -->
<para>
-Clear a flag in the meta data.
+
</para>
-@meta: the meta data
-@flag: the flag to clear
-<!-- ##### MACRO GST_IS_FAKESRC ##### -->
+<!-- ##### SIGNAL GstSrc::eos ##### -->
<para>
+An eos signal is triggered whenever the GstSrc has reached the end of
+the stream.
</para>
-@obj:
+@gstsrc: the object which received the signal.
+@arg1: the object which received the signal
-<!-- ##### SECTION ./tmpl/gstaudiosink.sgml:Long_Description ##### -->
+<!-- ##### STRUCT GstSrcClass ##### -->
<para>
</para>
-<!-- ##### SECTION ./tmpl/gstsink.sgml:Long_Description ##### -->
+<!-- ##### ENUM GstSrcFlags ##### -->
<para>
-The sink is the end of the filter graph. A typical sink would be an audio
-or a video card.
-
+Flags for the GstSrc element
</para>
+@GST_SRC_ASYNC: Indicates that this src is asynchronous
+@GST_SRC_FLAG_LAST: subclasses can use this to number their flags
-<!-- ##### MACRO GST_IS_BIN_CLASS ##### -->
+<!-- ##### STRUCT GstTee ##### -->
<para>
</para>
-@obj:
-<!-- ##### FUNCTION gst_esdsink_get_type ##### -->
+<!-- ##### STRUCT GstTeeClass ##### -->
<para>
</para>
-@Returns:
-<!-- ##### SECTION ./tmpl/GstElement.sgml:See_Also ##### -->
+<!-- ##### STRUCT GstThreadClass ##### -->
<para>
</para>
-<!-- ##### STRUCT GstEsdSinkClass ##### -->
+<!-- ##### ARG GstTypeFind:type ##### -->
<para>
-
+Query the element for the current mime type
</para>
-<!-- ##### MACRO GST_ELEMENT_IS_MULTI_IN ##### -->
+<!-- ##### SIGNAL GstXML::object-loaded ##### -->
<para>
-Query whether this object has multiple input pads.
-
+Is trigered whenever the state of an element changes
</para>
-@obj: Element to query for multiple input pads.
+@gstelement: the object which received the signal.
+@arg1: the new state of the object
-<!-- ##### SECTION ./tmpl/gstfilter.sgml:See_Also ##### -->
+<!-- ##### MACRO INFO ##### -->
<para>
</para>
+@cat:
+@format:
+@args...:
-<!-- ##### MACRO DEBUG_NOPREFIX ##### -->
+<!-- ##### MACRO INFO_ELEMENT ##### -->
<para>
</para>
+@cat:
+@element:
@format:
@args...:
-<!-- ##### ARG GstAudioSink:frequency ##### -->
+<!-- ##### STRUCT MetaAudioRaw ##### -->
<para>
</para>
+@meta:
+@format:
+@channels:
+@frequency:
+@bps:
-<!-- ##### STRUCT GstFdSrc ##### -->
+<!-- ##### STRUCT MetaAudioSpectrum ##### -->
<para>
</para>
+@meta:
+@bands:
+@channels:
+@interleaved:
+@lowfreq:
+@highfreq:
+@steps:
-<!-- ##### FUNCTION gst_props_register ##### -->
+<!-- ##### STRUCT MetaDGA ##### -->
<para>
</para>
-@factory:
-@Returns:
+@base:
+@swidth:
+@sheight:
+@bytes_per_line:
-<!-- ##### STRUCT GstThreadClass ##### -->
+<!-- ##### STRUCT MetaOverlay ##### -->
<para>
</para>
+@wx:
+@wy:
+@overlay_element:
+@clip_count:
+@overlay_clip:
+@width:
+@height:
+@did_overlay:
+@fully_obscured:
-<!-- ##### FUNCTION gst_element_load_thyself ##### -->
+<!-- ##### STRUCT MetaVideoRaw ##### -->
<para>
</para>
-@self:
-@parent:
-@Returns:
-@elements:
+@meta:
+@format:
+@visual:
+@width:
+@height:
+@overlay_info:
+@dga_info:
-<!-- ##### FUNCTION gst_src_signal_eos ##### -->
+<!-- ##### STRUCT OverlayClip ##### -->
<para>
</para>
-@src:
+@x1:
+@x2:
+@y1:
+@y2:
-<!-- ##### STRUCT GstHttpSrc ##### -->
+<!-- ##### MACRO STACK_SIZE ##### -->
<para>
</para>
-<!-- ##### STRUCT GstSrc ##### -->
+<!-- ##### FUNCTION gst_asyncdisksrc_get_type ##### -->
<para>
</para>
+@Returns:
-<!-- ##### SECTION ./tmpl/videoraw.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_audiosink_chain ##### -->
<para>
-Information about video buffers.
+
</para>
+@pad:
+@buf:
-<!-- ##### FUNCTION gst_bin_add_managed_element ##### -->
+<!-- ##### FUNCTION gst_audiosink_get_type ##### -->
<para>
</para>
-@bin:
-@element:
+@Returns:
-<!-- ##### FUNCTION gst_queue_new ##### -->
+<!-- ##### FUNCTION gst_audiosink_new ##### -->
<para>
</para>
@name:
@Returns:
-<!-- ##### MACRO GST_THREAD_CLASS ##### -->
+<!-- ##### FUNCTION gst_audiosink_set_channels ##### -->
<para>
</para>
-@klass:
+@audiosink:
+@channels:
-<!-- ##### TYPEDEF GstPropsFactoryEntry ##### -->
+<!-- ##### FUNCTION gst_audiosink_set_format ##### -->
<para>
</para>
+@audiosink:
+@format:
-<!-- ##### MACRO GST_IS_FILTER_CLASS ##### -->
+<!-- ##### FUNCTION gst_audiosink_set_frequency ##### -->
<para>
</para>
-@obj:
+@audiosink:
+@frequency:
-<!-- ##### MACRO GST_CONNECTION_CLASS ##### -->
+<!-- ##### FUNCTION gst_audiosink_sync_parms ##### -->
<para>
</para>
-@klass:
+@audiosink:
-<!-- ##### SECTION ./tmpl/gstgetbits.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_audiosrc_get_type ##### -->
<para>
</para>
+@Returns:
-<!-- ##### FUNCTION gst_connection_new ##### -->
+<!-- ##### FUNCTION gst_audiosrc_new ##### -->
<para>
</para>
@name:
@Returns:
-<!-- ##### MACRO GST_SINK ##### -->
+<!-- ##### FUNCTION gst_audiosrc_push ##### -->
<para>
</para>
-@obj:
+@src:
-<!-- ##### MACRO GST_FDSRC_CLASS ##### -->
+<!-- ##### FUNCTION gst_autoplug_caps_list ##### -->
<para>
</para>
-@klass:
+@autoplug:
+@srcpad:
+@sinkpad:
+@Varargs:
+@Returns:
+@srccaps:
+@sinkcaps:
-<!-- ##### MACRO GST_TYPE_FAKESRC ##### -->
+<!-- ##### FUNCTION gst_autoplugfactory_load_thyself ##### -->
<para>
</para>
+@parent:
+@Returns:
-<!-- ##### SECTION ./tmpl/plugin.sgml:Short_Description ##### -->
-
-
-
-<!-- ##### FUNCTION gst_pad_get_type ##### -->
+<!-- ##### FUNCTION gst_autoplugfactory_save_thyself ##### -->
<para>
</para>
+@factory:
+@parent:
@Returns:
-<!-- ##### SECTION ./tmpl/gstsink.sgml:See_Also ##### -->
+<!-- ##### FUNCTION gst_bin_add_managed_element ##### -->
<para>
</para>
+@bin:
+@element:
-<!-- ##### MACRO GST_IS_AUDIOSINK ##### -->
+<!-- ##### FUNCTION gst_bin_create_plan ##### -->
<para>
</para>
-@obj:
+@bin:
-<!-- ##### SECTION ./tmpl/gstfilter.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_bin_get_type ##### -->
<para>
-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.
+
</para>
+@Returns:
-<!-- ##### FUNCTION gst_tee_new_pad ##### -->
+<!-- ##### FUNCTION gst_bin_remove_managed_element ##### -->
<para>
</para>
-@tee:
-@Returns:
+@bin:
+@element:
-<!-- ##### MACRO GST_OBJECT ##### -->
+<!-- ##### FUNCTION gst_bin_schedule ##### -->
<para>
</para>
-@obj:
+@bin:
-<!-- ##### MACRO GST_STATE_PLAYING_TO_READY ##### -->
+<!-- ##### FUNCTION gst_bin_schedule_func ##### -->
<para>
-The Element is going from the PLAYING state to the READY state.
+
</para>
+@bin:
-<!-- ##### MACRO GST_IS_FDSINK ##### -->
+<!-- ##### FUNCTION gst_bin_set_element_manager ##### -->
<para>
</para>
-@obj:
+@element:
+@manager:
-<!-- ##### MACRO GST_DEBUG_ENTER_STRING ##### -->
+<!-- ##### FUNCTION gst_buffer_add_meta ##### -->
<para>
-Combine #GST_DEBUG_ENTER and #GST_DEBUG_SET_STRING.
+
</para>
+@buffer:
+@meta:
-<!-- ##### MACRO GST_IS_DISKSRC ##### -->
+<!-- ##### FUNCTION gst_buffer_get_first_meta ##### -->
<para>
</para>
-@obj:
+@buffer:
+@Returns:
-<!-- ##### MACRO GST_FAKESINK_CLASS ##### -->
+<!-- ##### FUNCTION gst_buffer_get_metas ##### -->
<para>
</para>
-@klass:
+@buffer:
+@Returns:
-<!-- ##### MACRO GST_TYPE_FDSINK ##### -->
+<!-- ##### FUNCTION gst_buffer_pool_destroy_buffer ##### -->
<para>
</para>
+@pool:
+@buffer:
-<!-- ##### SECTION ./tmpl/gstcolorspace.sgml:Short_Description ##### -->
-
-
+<!-- ##### FUNCTION gst_buffer_pool_new_buffer ##### -->
+<para>
-<!-- ##### SECTION ./tmpl/videoraw.sgml:Title ##### -->
-videoraw
+</para>
+@pool:
+@Returns:
-<!-- ##### MACRO GST_IS_FILTER ##### -->
+<!-- ##### FUNCTION gst_buffer_pool_set_create_function ##### -->
<para>
</para>
-@obj:
+@pool:
+@create:
+@user_data:
-<!-- ##### STRUCT MetaOverlay ##### -->
+<!-- ##### FUNCTION gst_buffer_pool_set_destroy_function ##### -->
<para>
</para>
-@wx:
-@wy:
-@overlay_element:
-@clip_count:
-@overlay_clip:
-@width:
-@height:
-@did_overlay:
-@fully_obscured:
+@pool:
+@destroy:
+@user_data:
-<!-- ##### MACRO GST_TYPE_FILTER ##### -->
+<!-- ##### FUNCTION gst_buffer_remove_meta ##### -->
<para>
</para>
+@buffer:
+@meta:
-<!-- ##### FUNCTION gst_identity_new ##### -->
+<!-- ##### FUNCTION gst_caps_list_check_compatibility ##### -->
<para>
</para>
-@name:
+@fromcaps:
+@tocaps:
@Returns:
-<!-- ##### MACRO GST_IS_AUDIOSRC_CLASS ##### -->
+<!-- ##### FUNCTION gst_caps_new_with_props ##### -->
<para>
</para>
-@obj:
+@name:
+@mime:
+@props:
+@Returns:
-<!-- ##### STRUCT GstIdentityClass ##### -->
+<!-- ##### FUNCTION gst_caps_register ##### -->
<para>
</para>
+@factory:
+@Returns:
-<!-- ##### MACRO GST_IS_PAD_CLASS ##### -->
+<!-- ##### FUNCTION gst_caps_register_count ##### -->
<para>
</para>
-@obj:
+@factory:
+@counter:
+@Returns:
+@count:
-<!-- ##### MACRO GST_IDENTITY_CLASS ##### -->
+<!-- ##### FUNCTION gst_connection_get_type ##### -->
<para>
</para>
-@klass:
+@Returns:
-<!-- ##### MACRO GST_SINK_FLAG_LAST ##### -->
+<!-- ##### FUNCTION gst_connection_new ##### -->
<para>
</para>
+@name:
+@Returns:
-<!-- ##### MACRO GST_IS_FDSINK_CLASS ##### -->
+<!-- ##### FUNCTION gst_connection_push ##### -->
<para>
</para>
-@obj:
+@connection:
-<!-- ##### MACRO GST_SRC_FLAGS ##### -->
+<!-- ##### FUNCTION gst_disksrc_get_type ##### -->
<para>
-This macro returns the entire set of flags for the object.
+
</para>
-@obj: GstSrc to return flags for.
+@Returns:
-<!-- ##### STRUCT GstFakeSinkClass ##### -->
+<!-- ##### FUNCTION gst_element_change_state ##### -->
<para>
</para>
+@element:
+@state:
+@Returns:
-<!-- ##### ARG GstAsyncDiskSrc:length ##### -->
+<!-- ##### FUNCTION gst_element_get_type ##### -->
<para>
-Get the size of the current file.
-</para>
+</para>
-<!-- ##### SECTION ./tmpl/gstaudiosrc.sgml:Short_Description ##### -->
-
+@Returns:
+<!-- ##### FUNCTION gst_element_load_thyself ##### -->
+<para>
-<!-- ##### SECTION ./tmpl/gstsrc.sgml:Short_Description ##### -->
-The start point of a filter graph
+</para>
+@self:
+@parent:
+@Returns:
+@elements:
-<!-- ##### FUNCTION gst_src_push ##### -->
+<!-- ##### FUNCTION gst_element_loopfunc_wrapper ##### -->
<para>
-
</para>
-@src:
+@argc:
+@argv:
+@Returns:
-<!-- ##### MACRO GST_IS_ESDSINK ##### -->
+<!-- ##### FUNCTION gst_element_new ##### -->
<para>
</para>
-@obj:
+@Returns:
-<!-- ##### FUNCTION gst_sinesrc_push ##### -->
+<!-- ##### FUNCTION gst_element_request_pad ##### -->
<para>
</para>
-@src:
+@element:
+@templ:
+@Returns:
+@temp:
-<!-- ##### FUNCTION gst_bin_create_plan ##### -->
+<!-- ##### FUNCTION gst_element_save_thyself ##### -->
<para>
</para>
-@bin:
+@element:
+@parent:
+@Returns:
-<!-- ##### FUNCTION gst_props_register_count ##### -->
+<!-- ##### FUNCTION gst_elementfactory_add_sink ##### -->
<para>
</para>
-@factory:
-@counter:
-@Returns:
+@elementfactory:
+@id:
-<!-- ##### ARG GstFakeSink:num_sources ##### -->
+<!-- ##### FUNCTION gst_elementfactory_add_src ##### -->
<para>
</para>
+@elementfactory:
+@id:
-<!-- ##### MACRO GST_PROPS_FLOAT_RANGE_STRING ##### -->
+<!-- ##### FUNCTION gst_elementfactory_can_sink_caps_list ##### -->
<para>
</para>
-@a:
-@b:
+@factory:
+@caps:
+@Returns:
-<!-- ##### MACRO GST_FAKESRC_CLASS ##### -->
+<!-- ##### FUNCTION gst_elementfactory_can_src_caps_list ##### -->
<para>
</para>
-@klass:
+@factory:
+@caps:
+@Returns:
-<!-- ##### ARG GstQueue:timeout ##### -->
+<!-- ##### FUNCTION gst_elementfactory_destroy ##### -->
<para>
</para>
+@elementfactory:
-<!-- ##### MACRO COTHREAD_STACKSIZE ##### -->
+<!-- ##### FUNCTION gst_elementfactory_load_thyself ##### -->
<para>
-The default stack size of a cothread.
+
</para>
+@parent:
+@Returns:
-<!-- ##### SECTION ./tmpl/gstesdsink.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_elementfactory_register ##### -->
<para>
</para>
+@elementfactory:
-<!-- ##### STRUCT GstBinClass ##### -->
+<!-- ##### FUNCTION gst_elementfactory_save_thyself ##### -->
<para>
</para>
+@factory:
+@parent:
+@Returns:
-<!-- ##### MACRO GST_TYPE_DISKSRC ##### -->
+<!-- ##### FUNCTION gst_esdsink_chain ##### -->
<para>
</para>
+@pad:
+@buf:
-<!-- ##### FUNCTION gst_audiosrc_get_type ##### -->
+<!-- ##### FUNCTION gst_esdsink_get_type ##### -->
<para>
</para>
@Returns:
-<!-- ##### FUNCTION gst_httpsrc_get_type ##### -->
+<!-- ##### FUNCTION gst_esdsink_new ##### -->
<para>
</para>
+@name:
@Returns:
-<!-- ##### MACRO GST_DISKSRC_CLASS ##### -->
+<!-- ##### FUNCTION gst_esdsink_set_channels ##### -->
<para>
</para>
-@klass:
+@esdsink:
+@channels:
-<!-- ##### MACRO GST_ESDSINK_CLASS ##### -->
+<!-- ##### FUNCTION gst_esdsink_set_format ##### -->
<para>
</para>
-@klass: <<<<<<< gstreamer-unused.sgml
+@esdsink:
+@format:
-<!-- ##### MACRO GST_PAD_FACTORY_REQUEST ##### -->
+<!-- ##### FUNCTION gst_esdsink_set_frequency ##### -->
<para>
-Indicates that this pad will be available on request. Use
-this in the factory definition.
+
</para>
+@esdsink:
+@frequency:
-<!-- ##### FUNCTION gst_audiosink_sync_parms ##### -->
+<!-- ##### FUNCTION gst_esdsink_sync_parms ##### -->
<para>
</para>
-@audiosink:
+@esdsink:
-<!-- ##### MACRO GST_IS_FAKESINK ##### -->
+<!-- ##### FUNCTION gst_fakesink_chain ##### -->
<para>
</para>
-@obj:
+@pad:
+@buf:
-<!-- ##### MACRO GST_STATE_UNSET ##### -->
+<!-- ##### FUNCTION gst_fakesink_get_type ##### -->
<para>
-This macro unsets the given state on the element.
+
</para>
-@obj: Element to unset state of.
-@flag: State to unset, can be any number of bits in guint32.
+@Returns:
-<!-- ##### MACRO GST_QUEUE_CLASS ##### -->
+<!-- ##### FUNCTION gst_fakesink_new ##### -->
<para>
</para>
-@klass:
+@name:
+@Returns:
-<!-- ##### FUNCTION gst_pad_set_type_id ##### -->
+<!-- ##### FUNCTION gst_fakesrc_get_type ##### -->
<para>
</para>
-@pad:
-@id:
+@Returns:
-<!-- ##### MACRO GST_PAD_FACTORY_ALWAYS ##### -->
+<!-- ##### FUNCTION gst_fakesrc_new ##### -->
<para>
-Indicate that this pad will always be available.
-Use this in the factory definition.
+
</para>
+@name:
+@Returns:
-<!-- ##### FUNCTION gst_pad_add_ghost_parent ##### -->
+<!-- ##### FUNCTION gst_fakesrc_push ##### -->
<para>
</para>
-@pad:
-@parent:
+@src:
-<!-- ##### FUNCTION gst_audiosink_set_frequency ##### -->
+<!-- ##### FUNCTION gst_fdsink_chain ##### -->
<para>
</para>
-@audiosink:
-@frequency:
+@pad:
+@buf:
-<!-- ##### MACRO GST_TYPE_BIN ##### -->
+<!-- ##### FUNCTION gst_fdsink_get_type ##### -->
<para>
</para>
+@Returns:
-<!-- ##### FUNCTION gst_elementfactory_register ##### -->
+<!-- ##### FUNCTION gst_fdsink_new ##### -->
<para>
</para>
-@elementfactory:
+@name:
+@Returns:
-<!-- ##### ARG GstAudioSrc:bytes_per_read ##### -->
+<!-- ##### FUNCTION gst_fdsink_new_with_fd ##### -->
<para>
-The number of bytes per read.
+
</para>
+@name:
+@fd:
+@Returns:
-<!-- ##### FUNCTION gst_element_loopfunc_wrapper ##### -->
+<!-- ##### FUNCTION gst_fdsrc_get_type ##### -->
<para>
+
</para>
-@argc:
-@argv:
@Returns:
-<!-- ##### MACRO GST_IS_SINESRC ##### -->
+<!-- ##### FUNCTION gst_filter_get_type ##### -->
<para>
</para>
-@obj:
+@Returns:
-<!-- ##### FUNCTION gst_meta_new_size ##### -->
+<!-- ##### FUNCTION gst_filter_new ##### -->
<para>
</para>
-@size:
+@name:
@Returns:
-<!-- ##### MACRO ERROR_OBJECT ##### -->
+<!-- ##### FUNCTION gst_httpsrc_get_type ##### -->
<para>
</para>
-@element:
-@object:
-@format:
-@args...:
+@Returns:
-<!-- ##### FUNCTION gst_sinesrc_get_type ##### -->
+<!-- ##### FUNCTION gst_identity_chain ##### -->
<para>
</para>
-@Returns:
+@pad:
+@buf:
-<!-- ##### MACRO GST_IS_IDENTITY ##### -->
+<!-- ##### FUNCTION gst_identity_get_type ##### -->
<para>
</para>
-@obj:
+@Returns:
-<!-- ##### MACRO GST_AUDIOSRC ##### -->
+<!-- ##### FUNCTION gst_identity_new ##### -->
<para>
</para>
-@obj:
+@name:
+@Returns:
-<!-- ##### MACRO GST_TYPE_ESDSINK ##### -->
+<!-- ##### MACRO gst_meta_new ##### -->
<para>
-
+Create new meta data.
</para>
+@type: the type of the meta data to create
-<!-- ##### MACRO GST_FDSRC ##### -->
+<!-- ##### FUNCTION gst_meta_new_size ##### -->
<para>
</para>
-@obj:
+@size:
+@Returns:
-<!-- ##### SECTION ./tmpl/gstaudiosrc.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_meta_ref ##### -->
<para>
</para>
+@meta:
-<!-- ##### FUNCTION gst_audiosink_get_type ##### -->
+<!-- ##### FUNCTION gst_meta_unref ##### -->
<para>
</para>
-@Returns:
+@meta:
-<!-- ##### MACRO GST_OBJECT_CLASS ##### -->
+<!-- ##### FUNCTION gst_object_get_type ##### -->
<para>
</para>
-@klass:
+@Returns:
-<!-- ##### SECTION ./tmpl/gstconnection.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_object_new ##### -->
<para>
-A connection is a bas class for a generic connection between
-elements. A connection is typically a bas class for queues.
</para>
+@Returns:
-<!-- ##### MACRO GST_BUFFER ##### -->
+<!-- ##### FUNCTION gst_pad_add_ghost_parent ##### -->
<para>
</para>
-@buf:
+@pad:
+@parent:
-<!-- ##### MACRO GST_SRC_IS_ASYNC ##### -->
+<!-- ##### MACRO gst_pad_eos ##### -->
<para>
-Query a GstSrc for the ASYNC flag
+Call the EOS function of the pad
</para>
-@obj: The GstSrc to query
+@pad: the pad to call the eos function of.
-<!-- ##### MACRO GST_PIPELINE ##### -->
+<!-- ##### FUNCTION gst_pad_eos_func ##### -->
<para>
</para>
-@obj:
+@pad:
+@Returns:
-<!-- ##### MACRO GST_STATE_SET ##### -->
+<!-- ##### FUNCTION gst_pad_get_caps_by_name ##### -->
<para>
-This macro sets the given state on the element.
+
</para>
-@obj: Element to set state of.
-@flag: State to set, can be any number of bits in guint32.
+@pad:
+@name:
+@Returns:
-<!-- ##### FUNCTION gst_fakesink_get_type ##### -->
+<!-- ##### FUNCTION gst_pad_get_caps_list ##### -->
<para>
</para>
+@pad:
@Returns:
-<!-- ##### MACRO GST_TYPE_CONNECTION ##### -->
+<!-- ##### FUNCTION gst_pad_get_directory ##### -->
<para>
</para>
+@pad:
+@Returns:
-<!-- ##### ENUM GstMetaFlags ##### -->
+<!-- ##### FUNCTION gst_pad_get_ghost_parents ##### -->
<para>
-Flags indicating properties about the meta data.
+
</para>
-@GST_META_FREEABLE: the meta data can be freed
+@pad:
+@Returns:
-<!-- ##### SECTION ./tmpl/spectrum.sgml:See_Also ##### -->
+<!-- ##### FUNCTION gst_pad_get_type ##### -->
<para>
</para>
+@Returns:
-<!-- ##### MACRO GST_CONNECTION ##### -->
+<!-- ##### FUNCTION gst_pad_get_type_id ##### -->
<para>
</para>
-@obj:
-
-<!-- ##### SECTION ./tmpl/videoraw.sgml:Short_Description ##### -->
-Information about video buffers.
-
+@pad:
+@Returns:
-<!-- ##### FUNCTION gst_fdsink_get_type ##### -->
+<!-- ##### FUNCTION gst_pad_handle_qos ##### -->
<para>
</para>
-@Returns:
+@pad:
+@qos_message:
-<!-- ##### FUNCTION gst_src_push_region ##### -->
+<!-- ##### FUNCTION gst_pad_pull_region ##### -->
<para>
</para>
-@src:
+@pad:
@offset:
@size:
+@Returns:
-<!-- ##### STRUCT GstPipelineClass ##### -->
+<!-- ##### FUNCTION gst_pad_remove_ghost_parent ##### -->
<para>
</para>
+@pad:
+@parent:
-<!-- ##### MACRO DEBUG_ENTER ##### -->
+<!-- ##### FUNCTION gst_pad_save_thyself ##### -->
<para>
</para>
-@format:
-@args...:
+@pad:
+@parent:
+@Returns:
-<!-- ##### SIGNAL GstXML::object-loaded ##### -->
+<!-- ##### FUNCTION gst_pad_select ##### -->
<para>
-Is trigered whenever the state of an element changes
+
</para>
-@gstelement: the object which received the signal.
-@arg1: the new state of the object
+@nextpad:
+@Varargs:
+@Returns:
-<!-- ##### MACRO GST_ELEMENT_CLASS ##### -->
+<!-- ##### FUNCTION gst_pad_set_caps_list ##### -->
<para>
</para>
-@klass:
+@pad:
+@caps:
-<!-- ##### FUNCTION gst_fakesrc_new ##### -->
+<!-- ##### FUNCTION gst_pad_set_eos ##### -->
<para>
</para>
-@name:
+@pad:
@Returns:
-<!-- ##### FUNCTION gst_fakesrc_get_type ##### -->
+<!-- ##### FUNCTION gst_pad_set_eos_function ##### -->
<para>
</para>
-@Returns:
-
-<!-- ##### SECTION ./tmpl/audioraw.sgml:Short_Description ##### -->
-Information about audio buffers.
-
+@pad:
+@eos:
-<!-- ##### SECTION ./tmpl/videoraw.sgml:See_Also ##### -->
+<!-- ##### FUNCTION gst_pad_set_pull_function ##### -->
<para>
</para>
+@pad:
+@pull:
-<!-- ##### SECTION ./tmpl/gstfilter.sgml:Short_Description ##### -->
-Take data in and spit data out
-
-
-<!-- ##### TYPEDEF GstPadFactory[] ##### -->
+<!-- ##### FUNCTION gst_pad_set_qos_function ##### -->
<para>
-The padfactory.
+
</para>
+@pad:
+@qos:
-<!-- ##### MACRO GST_SRC_ASYNC ##### -->
+<!-- ##### FUNCTION gst_pad_set_type_id ##### -->
<para>
-This macro checks to see if the GST_SRC_ASYNC flag is set.
+
</para>
-@obj: GstSrc to check for flag in.
+@pad:
+@id:
-<!-- ##### STRUCT GstPluginElement ##### -->
+<!-- ##### FUNCTION gst_padtemplate_create ##### -->
<para>
</para>
+@name_template:
+@direction:
+@presence:
+@caps:
+@Returns:
-<!-- ##### MACRO GST_TYPE_SINESRC ##### -->
+<!-- ##### FUNCTION gst_pipeline_get_type ##### -->
<para>
</para>
+@Returns:
-<!-- ##### SECTION ./tmpl/gstmeta.sgml:Title ##### -->
-GstMeta
-
-
-<!-- ##### TYPEDEF GstCapsFactory ##### -->
+<!-- ##### FUNCTION gst_plugin_add_autoplugger ##### -->
<para>
</para>
+@plugin:
+@factory:
-<!-- ##### STRUCT GstFdSrcClass ##### -->
+<!-- ##### FUNCTION gst_plugin_add_factory ##### -->
<para>
</para>
+@plugin:
+@factory:
-<!-- ##### MACRO GST_CPU_FLAG_SSE ##### -->
+<!-- ##### FUNCTION gst_plugin_add_type ##### -->
<para>
-A flag indicating that SSE instructions are supported.
+
</para>
+@plugin:
+@factory:
-<!-- ##### MACRO GST_IS_CONNECTION_CLASS ##### -->
+<!-- ##### FUNCTION gst_plugin_get_autoplug_list ##### -->
<para>
</para>
-@obj:
+@plugin:
+@Returns:
-<!-- ##### FUNCTION gst_util_get_widget_arg ##### -->
+<!-- ##### FUNCTION gst_plugin_get_factory_list ##### -->
<para>
</para>
-@object:
-@argname:
+@plugin:
@Returns:
-<!-- ##### ARG GstAsyncDiskSrc:size ##### -->
+<!-- ##### FUNCTION gst_plugin_get_type_list ##### -->
<para>
</para>
+@plugin:
+@Returns:
-<!-- ##### STRUCT GstDiskSrcClass ##### -->
+<!-- ##### FUNCTION gst_plugin_init ##### -->
<para>
</para>
-<!-- ##### MACRO GST_DEBUG_SET_STRING ##### -->
+<!-- ##### FUNCTION gst_plugin_load_autoplugfactory ##### -->
<para>
-Set the debug string for the current function, typically containing the arguments
-to the current function, i.e. "('element')"
+
</para>
-@format: printf-style format string
-@args...: printf arguments
+@name:
+@Returns:
-<!-- ##### FUNCTION gst_element_get_type ##### -->
+<!-- ##### FUNCTION gst_plugin_load_elementfactory ##### -->
<para>
</para>
+@name:
@Returns:
-<!-- ##### FUNCTION gst_bin_remove_managed_element ##### -->
+<!-- ##### FUNCTION gst_plugin_load_typefactory ##### -->
<para>
</para>
-@bin:
-@element:
+@mime:
-<!-- ##### STRUCT GstElementClass ##### -->
+<!-- ##### FUNCTION gst_props_register ##### -->
<para>
</para>
+@factory:
+@Returns:
-<!-- ##### MACRO GST_META_FLAG_SET ##### -->
+<!-- ##### FUNCTION gst_props_register_count ##### -->
<para>
-Set a flag in the meta data.
+
</para>
-@meta: the meta data
-@flag: the flag to set
+@factory:
+@counter:
+@Returns:
-<!-- ##### MACRO GST_IS_SRC ##### -->
+<!-- ##### FUNCTION gst_queue_chain ##### -->
<para>
</para>
-@obj:
+@pad:
+@buf:
-<!-- ##### SECTION ./tmpl/audioraw.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_queue_get_type ##### -->
<para>
-Information about audio buffers.
+
</para>
+@Returns:
-<!-- ##### ENUM GstPropsId ##### -->
+<!-- ##### FUNCTION gst_queue_new ##### -->
<para>
</para>
-@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:
+@name:
+@Returns:
-<!-- ##### ENUM GstCapsDefinition ##### -->
+<!-- ##### FUNCTION gst_queue_push ##### -->
<para>
</para>
-@GST_CAPS_ALWAYS:
-@GST_CAPS_MAYBE:
+@connection:
-<!-- ##### MACRO GST_META_FLAG_IS_SET ##### -->
+<!-- ##### FUNCTION gst_sinesrc_get_type ##### -->
<para>
-Check if a given flag is set.
+
</para>
-@meta: the meta data to test
-@flag: the flag to test
+@Returns:
-<!-- ##### STRUCT GstPadClass ##### -->
+<!-- ##### FUNCTION gst_sinesrc_new ##### -->
<para>
</para>
+@name:
+@Returns:
-<<<<<<< gstreamer-unused.sgml
-
-
-<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:See_Also ##### -->
+<!-- ##### FUNCTION gst_sinesrc_push ##### -->
<para>
</para>
+@src:
-<!-- ##### MACRO GST_HTTPSRC ##### -->
->>>>>>> 1.23.2.3
+<!-- ##### FUNCTION gst_sink_get_type ##### -->
<para>
</para>
-@obj:
+@Returns:
-<!-- ##### STRUCT GstQueue ##### -->
+<!-- ##### FUNCTION gst_sink_new ##### -->
<para>
</para>
+@name:
+@Returns:
-<!-- ##### MACRO gst_meta_new ##### -->
+<!-- ##### FUNCTION gst_src_get_type ##### -->
<para>
-Create new meta data.
+
</para>
-@type: the type of the meta data to create
+@Returns:
-<!-- ##### FUNCTION plugin_initialize ##### -->
+<!-- ##### FUNCTION gst_src_push ##### -->
<para>
</para>
+@src:
-<!-- ##### FUNCTION gst_caps_register ##### -->
+<!-- ##### FUNCTION gst_src_push_region ##### -->
<para>
</para>
-@factory:
-@Returns:
+@src:
+@offset:
+@size:
-<!-- ##### ARG GstAsyncDiskSrc:location ##### -->
+<!-- ##### FUNCTION gst_src_signal_eos ##### -->
<para>
-Specify the location of the file to read.
+
</para>
+@src:
-<!-- ##### MACRO GST_TEE_CLASS ##### -->
+<!-- ##### FUNCTION gst_tee_chain ##### -->
<para>
</para>
-@klass:
+@pad:
+@buf:
-<!-- ##### FUNCTION gst_queue_get_type ##### -->
+<!-- ##### FUNCTION gst_tee_get_type ##### -->
<para>
</para>
@Returns:
-<!-- ##### MACRO DEBUG_LEAVE ##### -->
+<!-- ##### FUNCTION gst_tee_new ##### -->
<para>
</para>
-@format:
-@args...:
+@name:
+@Returns:
-<!-- ##### FUNCTION gst_audiosink_set_format ##### -->
+<!-- ##### FUNCTION gst_tee_new_pad ##### -->
<para>
</para>
-@audiosink:
-@format:
+@tee:
+@Returns:
-<!-- ##### SECTION ./tmpl/spectrum.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_thread_get_type ##### -->
<para>
-Frequencies of a spectrum analysis.
</para>
+@Returns:
-<!-- ##### SECTION ./tmpl/gstaudiosrc.sgml:Title ##### -->
-GstAudioSrc
-
-
-<!-- ##### MACRO GST_PAD_FACTORY_SOMETIMES ##### -->
+<!-- ##### FUNCTION gst_thread_iterate ##### -->
<para>
-Indicate that this pad will become available depending
-on the media type. Use this in the factory definition.
+
</para>
+@thread:
-<!-- ##### MACRO INFO ##### -->
+<!-- ##### FUNCTION gst_thread_main_loop ##### -->
<para>
</para>
-@cat:
-@format:
-@args...:
+@arg:
-<!-- ##### SECTION ./tmpl/gstasyncdisksrc.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION gst_type_add_sink ##### -->
<para>
-Reads data from a file. You can seek to a specific location by setting
-the offset.
+
</para>
+@id:
+@sink:
-<!-- ##### FUNCTION gst_sinesrc_new ##### -->
+<!-- ##### FUNCTION gst_type_add_src ##### -->
<para>
</para>
-@name:
-@Returns:
+@id:
+@src:
-<!-- ##### MACRO GST_IS_ASYNCDISKSRC_CLASS ##### -->
+<!-- ##### FUNCTION gst_type_dump ##### -->
<para>
</para>
-@obj:
-<!-- ##### FUNCTION gst_buffer_get_metas ##### -->
+<!-- ##### FUNCTION gst_type_get_sink_to_src ##### -->
<para>
</para>
-@buffer:
+@sinkid:
+@srcid:
@Returns:
-<!-- ##### ARG GstAudioSrc:curoffset ##### -->
+<!-- ##### FUNCTION gst_type_get_sinks ##### -->
<para>
-Get the current number of bytes read.
+
</para>
+@id:
+@Returns:
-<!-- ##### FUNCTION gst_plugin_init ##### -->
+<!-- ##### FUNCTION gst_type_get_srcs ##### -->
<para>
</para>
+@id:
+@Returns:
-<!-- ##### STRUCT MetaAudioSpectrum ##### -->
+<!-- ##### FUNCTION gst_type_initialize ##### -->
<para>
</para>
-@meta:
-@bands:
-@channels:
-@interleaved:
-@lowfreq:
-@highfreq:
-@steps:
-
-<!-- ##### SECTION ./tmpl/plugin.sgml:Title ##### -->
-plugin
-
-<!-- ##### MACRO GST_IS_PAD ##### -->
+<!-- ##### FUNCTION gst_type_load_thyself ##### -->
<para>
</para>
-@obj:
+@parent:
+@Returns:
-<!-- ##### STRUCT GstFakeSrcClass ##### -->
+<!-- ##### FUNCTION gst_type_save_thyself ##### -->
<para>
</para>
+@type:
+@parent:
+@Returns:
-<!-- ##### FUNCTION gst_type_dump ##### -->
+<!-- ##### FUNCTION gst_typefactory_load_thyself ##### -->
<para>
</para>
+@parent:
+@Returns:
-<!-- ##### ARG GstAudioSink:channels ##### -->
+<!-- ##### FUNCTION gst_typefactory_save_thyself ##### -->
<para>
</para>
+@factory:
+@parent:
+@Returns:
-<!-- ##### MACRO GST_BIN_CLASS ##### -->
+<!-- ##### FUNCTION gst_util_get_widget_arg ##### -->
<para>
</para>
-@klass:
+@object:
+@argname:
+@Returns:
-<!-- ##### MACRO GST_HTTPSRC_CLASS ##### -->
+<!-- ##### FUNCTION gst_xml_new_from_memory ##### -->
<para>
</para>
-@klass:
+@buffer:
+@size:
+@root:
+@Returns:
-<!-- ##### MACRO GST_ASYNCDISKSRC ##### -->
+<!-- ##### FUNCTION plugin_initialize ##### -->
<para>
</para>
-@obj:
-<!-- ##### ARG GstPad:active ##### -->
+<!-- ##### FUNCTION plugin_load ##### -->
<para>
-Indicates this pad is active
+
</para>
+@name:
+@Returns:
-<!-- ##### STRUCT GstTee ##### -->
+<!-- ##### FUNCTION plugin_load_absolute ##### -->
<para>
</para>
+@name:
+@Returns:
-<!-- ##### SECTION ./tmpl/gstsrc.sgml:Long_Description ##### -->
+<!-- ##### FUNCTION plugin_load_all ##### -->
<para>
-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.
</para>
</para>
-<!-- ##### ARG GstTee:num_pads ##### -->
+<!-- ##### ARG GstTee:num-pads ##### -->
<para>
</para>
@Returns:
-<!-- ##### ARG GstThread:create_thread ##### -->
+<!-- ##### ARG GstThread:create-thread ##### -->
<para>
TRUE if the thread should be created.
@id:
@mime:
@exts:
-@typefindfuncs:
+@factories:
<!-- ##### STRUCT GstTypeFactory ##### -->
<para>
The struct with the typefactory information.
</para>
+@feature:
@mime:
@exts:
@typefindfunc:
@Returns:
-<!-- ##### FUNCTION gst_typefactory_load_thyself ##### -->
-<para>
-
-</para>
-
-@parent:
-@Returns:
-
-
-<!-- ##### FUNCTION gst_typefactory_save_thyself ##### -->
-<para>
-
-</para>
-
-@factory:
-@parent:
-@Returns:
-
-
-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
- - EOS
- - Seek
- - caps nego??
- - bufferpool get??
- - ...
-
-Assumptions for events
-----------------------
+ 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.
-- 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)
+ - EOS
+ A plugin can notify other plugins that it has run out-of-data.
-Questions
----------
+ - Seek
+ Used to notify plugins that they need to seek to a certain byte offset
+ or timestamp.
-limit the valid directions an event can travel in? ie. Can EOS only
-travel downstream (left to right)?
+ - discontinuous
+ A plugin has detected a discontinuity in the stream. Other plugins
+ might need to resync.
-eg. Seek travels upstream, but it makes sense to also make it travel
- downstream (the case of a disksink, where we overwrite the header)
+ - flush
+ Plugins need to get rid of any buffered data ASAP.
+ - caps nego??
+ - bufferpool get??
+ - ...
-Setting an event function
--------------------------
-void gst_pad_set_event_function (GstPad *pad, gint event_mask,
- GstEventFunction *function);
+application generated events
+----------------------------
+The application can insert events into the pipeline at arbirary
+places. This will be done by calling gst_pad_event() on a pad.
-event masks:
+A first implementation will only cover inserting events on src pads
+since inserting events on sinkpads needs changes to the scheduler.
-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
----------------
+Effects of events on plugins
+----------------------------
-typedef struct {
- GstEventType type;
- GstEventMinorType minor;
- guint64 timestamp; /* also sequence number ?? */
+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.
- union {
- /* EOS stuff */
- /* QoS stuff */
- /* Seek stuff */
- GstSeekType type; /* time, bytes, ... */
- gint64 offset;
- gint64 lenth;
- /* Caps stuff */
- GstCaps *caps;
- } data;
-} GstEvent;
+use cases
+---------
-typedef enum {
- GST_EVENT_MINOR_NONE,
- /* EOS stuff */
+1) filesrc ! fakesink
- /* QoS stuff */
- /* Seek stuff */
- GST_EVENT_MINOR_OFFSET,
- GST_EVENT_MINOR_TIME,
+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)
- /* caps nego stuff */
- GST_EVENT_MINOR_CAPS_TRY,
- GST_EVENT_MINOR_CAPS_START,
- GST_EVENT_MINOR_CAPS_FINAL,
-} GstEventMinorType;
+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.
-Receiving events
-----------------
+3) filesrc ! mpeg2parse video_0! queue ! { mpeg2dec ! xvideosink }
-a sample GstEventFunction, the event functions returns TRUE if the event is handled,
-FALSE otherwise.
+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.
-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;
-}
+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.
-Default event handler for pads
-------------------------------
+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.
-gboolean
-gst_pad_handle_event (GstPad *pad, GstEvent *event)
-{
- GstElement *element;
- GList *pads;
- GstPad *srcpad;
- gboolean result = TRUE;
- GstPadDirection dir = GST_PAD_DIRECTION (pad);
+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).
- g_return_val_if_fail (pad != NULL, FALSE);
- g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
+4)...
- element = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (pad)));
+Insert impossible case here..
- /* 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;
-}
-
--- /dev/null
+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;
+}
+
+
GstEditorProject *
gst_editor_project_new_from_file (const guchar *fname)
{
+#ifndef GST_DISABLE_LOADSAVE
GstEditorProject *editorproject;
GstXML *xml;
GList *elements;
elements = g_list_next (elements);
}
-
return editorproject;
+#else
+ return NULL;
+#endif
}
void
while (elements) {
GstElement *element = (GstElement *) elements->data;
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile (fname, gst_xml_write (element));
+#endif
elements = g_list_next (elements);
}
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 \
gst_element_set_state (pipeline, GST_STATE_PLAYING);
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("xmlTest.gst", gst_xml_write (GST_ELEMENT (pipeline)));
+#endif
}
gboolean
}
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);
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);
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
gstcpu.c \
gstelement.c \
gstelementfactory.c \
+ gstevent.c \
gstextratypes.c \
gstinfo.c \
gstpad.c \
libgstinclude_HEADERS = \
cothreads.h \
gst.h \
+ gstconfig.h \
$(GST_OBJECT_MODEL_HDR) \
gstobject.h \
gsttypes.h \
gstcaps.h \
gstclock.h \
gstcpu.h \
+ gstdata.h \
gstelement.h \
gstevent.h \
gstextratypes.h \
-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)
// 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");
}
GSTHTTPSRC=
endif
+#CFLAGS += -O2 -Wall -finstrument-functions -DGST_ENABLE_FUNC_INSTRUMENTATION
+
libgstelements_la_DEPENDENCIES = ../libgst.la
libgstelements_la_SOURCES = \
gstelements.c \
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)
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);
}
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;
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);
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
// 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;
}
}
-/**
- * gst_disksrc_get:
- * @pad: #GstPad to push a buffer from
- *
- * Push a new buffer from the disksrc at the current offset.
- */
-static GstBuffer *
-gst_disksrc_get (GstPad *pad)
+static GstBuffer*
+gst_disksrc_buffer_new (GstBufferPool *pool, gint64 location, gint size, gpointer user_data)
{
GstDiskSrc *src;
GstBuffer *buf;
- g_return_val_if_fail (pad != NULL, NULL);
- src = GST_DISKSRC (gst_pad_get_parent (pad));
- g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL);
-
-
- /* deal with EOF state */
- if (src->curoffset >= src->size) {
- GST_DEBUG (0,"map offset %ld >= size %ld --> eos\n", src->curoffset, src->size);
- gst_pad_event(pad, GST_EVENT_EOS, 0LL, 0);
- buf = gst_buffer_new();
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_EOS);
- return buf;
- }
+ src = GST_DISKSRC (user_data);
- /* 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_DATA (buf) = src->map + location;
+ GST_BUFFER_OFFSET (buf) = location;
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;
+ 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));
- //gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ return buf;
+}
- src->curoffset += GST_BUFFER_SIZE (buf);
+static void
+gst_disksrc_buffer_free (GstBuffer *buf)
+{
+ // FIXME do something here
+}
- if (src->new_seek) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
- GST_DEBUG (0,"new seek\n");
- src->new_seek = FALSE;
+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);
}
- /* we're done, return the buffer */
- return buf;
+ return src->bufferpool;
}
/**
- * gst_disksrc_get_region:
- * @src: #GstSrc to push a buffer from
- * @offset: offset in file
- * @size: number of bytes
+ * gst_disksrc_get:
+ * @pad: #GstPad to push a buffer from
*
- * Push a new buffer from the disksrc of given size at given offset.
+ * Push a new buffer from the disksrc at the current offset.
*/
static GstBuffer *
-gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
+gst_disksrc_get (GstPad *pad)
{
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
+ if (src->curoffset >= src->size) {
+ GST_DEBUG (0,"map offset %ld >= size %ld --> eos\n", src->curoffset, src->size);
+ gst_pad_event(pad, GST_EVENT_EOS, 0LL, 0);
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);
+ // FIXME use a bufferpool
+ buf = gst_disksrc_buffer_new (NULL, src->curoffset, src->bytes_per_read, src);
- 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_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ src->curoffset += GST_BUFFER_SIZE (buf);
- GST_DEBUG (0,"map %p, offset %lld, size %d\n", src->map, offset, GST_BUFFER_SIZE (buf));
+ if (src->new_seek) {
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
+ GST_DEBUG (0,"new seek\n");
+ src->new_seek = FALSE;
+ }
- /* we're done, return the buffer off now */
+ /* we're done, return the buffer */
return buf;
}
-
/* open the file and mmap it, necessary to go to READY state */
static gboolean
gst_disksrc_open_file (GstDiskSrc *src)
gchar *filename;
/* fd */
gint fd;
+ GstBufferPool *bufferpool;
/* mapping parameters */
gulong size; /* how long is the file? */
ARG_0,
ARG_NUM_SINKS,
ARG_SILENT,
+ ARG_DUMP,
};
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);
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 };
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,
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;
case ARG_SILENT:
sink->silent = g_value_get_boolean (value);
break;
+ case ARG_DUMP:
+ sink->dump = g_value_get_boolean (value);
+ break;
default:
break;
}
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;
/**
* 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
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);
}
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");
- }
-}
GSList *sinkpads;
gint numsinkpads;
gboolean silent;
+ gboolean dump;
};
struct _GstFakeSinkClass {
*/
+#include <stdlib.h>
+#include <string.h>
+
#include <gstfakesrc.h>
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,
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);
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
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,
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
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*
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)
{
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)
{
GstFakeSrc *src;
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:
case ARG_SILENT:
src->silent = g_value_get_boolean (value);
break;
+ case ARG_DUMP:
+ src->dump = g_value_get_boolean (value);
+ break;
default:
break;
}
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;
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)
{
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)
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)
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;
}
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)
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);
} 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)
{
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) \
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 {
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <errno.h>
/**********************************************************************
"(C) 1999",
};
+//#define fs_print(format,args...) g_print(format, ## args)
+#define fs_print(format,args...)
+
#define GST_TYPE_FILESRC \
(gst_filesrc_get_type())
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 {
ARG_BLOCKSIZE,
ARG_OFFSET,
ARG_MAPSIZE,
+ ARG_TOUCH,
};
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;
src->map_regions = g_tree_new(gst_filesrc_bufcmp);
src->map_regions_lock = g_mutex_new();
+
+ src->seek_happened = FALSE;
}
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;
}
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;
{
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);
}
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);
}
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);
{
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;
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
if (readend > src->filelen) {
readsize = src->filelen - src->curoffset;
readend = src->curoffset;
- eof = TRUE;
}
// if the start is past the mapstart
// 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);
}
// 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
*(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;
{
g_return_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN));
+ g_print ("close\n");
/* close the file */
close (src->fd);
} else if (data == SEEK_END) {
src->curoffset = src->filelen - (guint64)location;
}
+ src->seek_happened = TRUE;
// push a discontinuous event?
return TRUE;
}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ * 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gstsinesrc.h>
+
+
+GstElementDetails gst_sinesrc_details = {
+ "Sine-wave src",
+ "Source/Audio",
+ "Create a sine wave of a given frequency and volume",
+ VERSION,
+ "Erik Walthinsen <omega@cse.ogi.edu>",
+ "(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;
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <config.h>
+#include <gst/gst.h>
+
+#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__ */
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);
}
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;
#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
return class->signals;
}
-
#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;
#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
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
#include "gst_private.h"
+#include "gstversion.h"
#include "gstcpu.h"
#include "gsttype.h"
#include "gstplugin.h"
#endif
#define MAX_PATH_SPLIT 16
+#define GST_PLUGIN_SEPARATOR ","
gchar *_gst_progname;
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";
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 ();
_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);
}
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;
}
}
}
+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,
(*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;
}
/* 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) {
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");
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;
+}
+
#include <gst/cothreads.h>
#include <gst/gstscheduler.h>
#include <gst/gsttimecache.h>
+#include <gst/gstevent.h>
#include <gst/gstparse.h>
#include <gst/gstextratypes.h>
*/
//#define GST_DEBUG_ENABLED
+
+#include <gst/gstconfig.h>
+
#include "gst_private.h"
#include "gstautoplug.h"
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 };
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;
}
return gst_autoplugfactory_create (factory);;
}
+#ifndef GST_DISABLE_REGISTRY
static xmlNodePtr
gst_autoplugfactory_save_thyself (GstObject *object, xmlNodePtr parent)
{
children = children->next;
}
}
+#endif /* GST_DISABLE_REGISTRY */
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
field = field->next;
}
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE */
/**
#include "gstbuffer.h"
+GType _gst_buffer_type;
+
static GMemChunk *_gst_buffer_chunk;
static GMutex *_gst_buffer_chunk_lock;
_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;
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);
}
/**
* Returns: new buffer
*/
GstBuffer*
-gst_buffer_new(void)
+gst_buffer_new (void)
{
GstBuffer *buffer;
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);
buffer->pool_private = NULL;
buffer->free = NULL;
buffer->copy = NULL;
-
+
return buffer;
}
* 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;
}
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
gst_buffer_ref (parent);
buffer->pool = NULL;
- // return the new subbuffer
+
return 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);
*
* 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) &&
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);
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);
}
/**
- * 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
*
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);
{
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);
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));
}
{
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 + 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 + (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;
- 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 (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);
}
#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 <gst/gstdata.h>
#include <gst/gstobject.h>
#ifdef HAVE_CONFIG_H
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)
} GstBufferFlags;
-
typedef struct _GstBuffer GstBuffer;
#include <gst/gstbufferpool.h>
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 */
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
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);
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
return result;
}
-#endif /* (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) ) */
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
#ifndef __GST_CAPS_H__
#define __GST_CAPS_H__
-#include <parser.h> // 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 <gst/gstconfig.h>
#include <gst/gstprops.h>
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__ */
--- /dev/null
+/* 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 <parser.h>
+
+ // 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__ */
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * 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 <gst/gstobject.h>
+
+#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__ */
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,
(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
}
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;
}
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;
}
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;
}
}
+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
}
}
- /* this is redundant, really, it will always return SUCCESS */
return return_val;
}
return element;
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE */
/**
* gst_element_set_sched:
#ifndef __GST_ELEMENT_H__
#define __GST_ELEMENT_H__
-#include <parser.h> // 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 <gst/gstconfig.h>
#include <gst/gstobject.h>
#include <gst/gstpad.h>
#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 */
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;
-
- guint16 numpads;
- guint16 numsrcpads;
- guint16 numsinkpads;
- GList *pads;
-
- GstElement *manager;
- GstSchedule *sched;
+ cothread_state *threadstate;
+
+ /* 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);
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);
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);
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
/*
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;
#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);
#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);
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wim.taymans@chello.be>
+ *
+ * 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;
+}
#define __GST_EVENT_H__
#include <gst/gstobject.h>
+#include <gst/gstdata.h>
#ifdef __cplusplus
extern "C" {
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 */
/***** 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));
#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 */
gchar *_gst_debug_nameof_funcptr (void *ptr);
+void gst_debug_print_stack_trace (void);
+
#endif /* __GSTINFO_H__ */
/* Object signals and args */
enum {
PARENT_SET,
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
OBJECT_SAVED,
#endif
LAST_SIGNAL
SO_LAST_SIGNAL
};
+GType _gst_object_type = 0;
+
typedef struct _GstSignalObject GstSignalObject;
typedef struct _GstSignalObjectClass GstSignalObjectClass;
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,
(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
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,
}
-#ifndef GST_DISABLE_LOADSAVE
+#ifndef GST_DISABLE_LOADSAVE_REGISTRY
/**
* gst_object_save_thyself:
* @object: GstObject to save
if (oclass->restore_thyself)
oclass->restore_thyself (object, parent);
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
/**
* gst_object_get_path_string:
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
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,
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
g_signal_emit_by_name (oclass->signal_object, name, object, self);
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
#ifndef __GST_OBJECT_H__
#define __GST_OBJECT_H__
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
+#include <gst/gstconfig.h>
#ifdef USE_GLIB2
#include <glib-object.h> // note that this gets wrapped in __GST_OBJECT_H__
#include <gst/gobject2gtk.h>
#endif
-#include <gst/gsttrace.h>
-#include <parser.h>
-
-#include <gst/gsttypes.h>
-
#ifdef HAVE_ATOMIC_H
#include <asm/atomic.h>
#endif
+#include <gst/gsttrace.h>
+#include <gst/gsttypes.h>
+
// FIXME
#include "gstlog.h"
extern "C" {
#endif /* __cplusplus */
+extern GType _gst_object_type;
+
+#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_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_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;
} 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)
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 */
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);
#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);
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,
(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
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,
(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
return self;
}
-#endif // GST_DISABLE_LOADSAVE
+#endif /* GST_DISABLE_LOADSAVE */
#ifndef gst_pad_push
/**
/***** 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);
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,
(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
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);
}
}
+
#ifndef __GST_PAD_H__
#define __GST_PAD_H__
-#include <parser.h> // 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 <gst/gstconfig.h>
#include <gst/gstobject.h>
#include <gst/gstbuffer.h>
extern "C" {
#endif /* __cplusplus */
+extern GType _gst_pad_type;
+extern GType _gst_real_pad_type;
+extern GType _gst_ghost_pad_type;
+
+//#define GST_TYPE_PARANOID
+
+/*
+ * Pad base class
+ */
+#define GST_TYPE_PAD (_gst_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_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;
* 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);
}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 */
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,
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));
gst_plugin_load_thyself (doc->xmlRootNode);
xmlFreeDoc (doc);
-#endif // GST_DISABLE_REGISTRY
+#endif /* GST_DISABLE_REGISTRY */
}
void
}
GST_INFO (GST_CAT_PLUGIN_LOADING, "added %d features ", featurecount);
}
-#endif // GST_DISABLE_REGISTRY
+#endif /* GST_DISABLE_REGISTRY */
/**
#ifndef __GST_PLUGIN_H__
#define __GST_PLUGIN_H__
-#include <gmodule.h>
-#include <parser.h> // NOTE: this is xml-config's fault
+#include <gst/gstconfig.h>
-// 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 <gmodule.h>
#include <gst/gstpluginfeature.h>
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)
{
return props;
}
-#endif /* (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) ) */
+#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
#ifndef __GST_PROPS_H__
#define __GST_PROPS_H__
-#include <glib.h>
-#include <parser.h> // 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 <gst/gstconfig.h>
+#include <glib.h>
typedef struct _GstProps GstProps;
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__ */
}
} else {
GST_INFO (GST_CAT_DATAFLOW,"NO ENABLED ELEMENTS IN CHAIN!!");
- //eos = TRUE;
+ eos = TRUE;
}
/*
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);
}
#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__ */
#ifndef __GST_XML_H__
#define __GST_XML_H__
-#ifndef GST_DISABLE_LOADSAVE
-
-#include <parser.h>
+#include <gst/gstconfig.h>
-// 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
+#ifndef GST_DISABLE_LOADSAVE
#include <gst/gstelement.h>
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+
+#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);
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <gst/gstpad.h>
+
+#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__ */
}
if (priv->src == NULL) {
- priv->src = gst_elementfactory_make ("disksrc", "srcelement");
+ priv->src = gst_elementfactory_make ("filesrc", "srcelement");
}
priv->uri = g_strdup (uri);
}
}
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile ("gstmediaplay.gst", gst_xml_write (gst_play_get_pipeline (play->play)));
+#endif
gdk_threads_enter();
gst_main();
+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
--- /dev/null
+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
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <gst/gst.h>
+#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 <omega@temple-baptist.com>",
+ "(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;i<identity->count;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;i<identity->count;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
+};
+
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2001 Erik Walthinsen <omega@temple-baptist.com>
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <gst/gstinfo.h>
+#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));
+ }
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 2001 Erik Walthinsen <omega@temple-baptist.com>
+ *
+ * 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 <gst/gstpad.h>
+
+#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__ */
GSTHTTPSRC=
endif
+#CFLAGS += -O2 -Wall -finstrument-functions -DGST_ENABLE_FUNC_INSTRUMENTATION
+
libgstelements_la_DEPENDENCIES = ../libgst.la
libgstelements_la_SOURCES = \
gstelements.c \
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)
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);
}
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;
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);
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
// 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;
}
}
-/**
- * gst_disksrc_get:
- * @pad: #GstPad to push a buffer from
- *
- * Push a new buffer from the disksrc at the current offset.
- */
-static GstBuffer *
-gst_disksrc_get (GstPad *pad)
+static GstBuffer*
+gst_disksrc_buffer_new (GstBufferPool *pool, gint64 location, gint size, gpointer user_data)
{
GstDiskSrc *src;
GstBuffer *buf;
- g_return_val_if_fail (pad != NULL, NULL);
- src = GST_DISKSRC (gst_pad_get_parent (pad));
- g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL);
-
-
- /* deal with EOF state */
- if (src->curoffset >= src->size) {
- GST_DEBUG (0,"map offset %ld >= size %ld --> eos\n", src->curoffset, src->size);
- gst_pad_event(pad, GST_EVENT_EOS, 0LL, 0);
- buf = gst_buffer_new();
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_EOS);
- return buf;
- }
+ src = GST_DISKSRC (user_data);
- /* 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_DATA (buf) = src->map + location;
+ GST_BUFFER_OFFSET (buf) = location;
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;
+ 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));
- //gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ return buf;
+}
- src->curoffset += GST_BUFFER_SIZE (buf);
+static void
+gst_disksrc_buffer_free (GstBuffer *buf)
+{
+ // FIXME do something here
+}
- if (src->new_seek) {
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
- GST_DEBUG (0,"new seek\n");
- src->new_seek = FALSE;
+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);
}
- /* we're done, return the buffer */
- return buf;
+ return src->bufferpool;
}
/**
- * gst_disksrc_get_region:
- * @src: #GstSrc to push a buffer from
- * @offset: offset in file
- * @size: number of bytes
+ * gst_disksrc_get:
+ * @pad: #GstPad to push a buffer from
*
- * Push a new buffer from the disksrc of given size at given offset.
+ * Push a new buffer from the disksrc at the current offset.
*/
static GstBuffer *
-gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
+gst_disksrc_get (GstPad *pad)
{
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
+ if (src->curoffset >= src->size) {
+ GST_DEBUG (0,"map offset %ld >= size %ld --> eos\n", src->curoffset, src->size);
+ gst_pad_event(pad, GST_EVENT_EOS, 0LL, 0);
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);
+ // FIXME use a bufferpool
+ buf = gst_disksrc_buffer_new (NULL, src->curoffset, src->bytes_per_read, src);
- 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_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+ src->curoffset += GST_BUFFER_SIZE (buf);
- GST_DEBUG (0,"map %p, offset %lld, size %d\n", src->map, offset, GST_BUFFER_SIZE (buf));
+ if (src->new_seek) {
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLUSH);
+ GST_DEBUG (0,"new seek\n");
+ src->new_seek = FALSE;
+ }
- /* we're done, return the buffer off now */
+ /* we're done, return the buffer */
return buf;
}
-
/* open the file and mmap it, necessary to go to READY state */
static gboolean
gst_disksrc_open_file (GstDiskSrc *src)
gchar *filename;
/* fd */
gint fd;
+ GstBufferPool *bufferpool;
/* mapping parameters */
gulong size; /* how long is the file? */
ARG_0,
ARG_NUM_SINKS,
ARG_SILENT,
+ ARG_DUMP,
};
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);
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 };
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,
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;
case ARG_SILENT:
sink->silent = g_value_get_boolean (value);
break;
+ case ARG_DUMP:
+ sink->dump = g_value_get_boolean (value);
+ break;
default:
break;
}
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;
/**
* 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
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);
}
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");
- }
-}
GSList *sinkpads;
gint numsinkpads;
gboolean silent;
+ gboolean dump;
};
struct _GstFakeSinkClass {
*/
+#include <stdlib.h>
+#include <string.h>
+
#include <gstfakesrc.h>
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,
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);
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
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,
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
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*
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)
{
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)
{
GstFakeSrc *src;
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:
case ARG_SILENT:
src->silent = g_value_get_boolean (value);
break;
+ case ARG_DUMP:
+ src->dump = g_value_get_boolean (value);
+ break;
default:
break;
}
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;
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)
{
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)
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)
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;
}
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)
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);
} 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)
{
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) \
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 {
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <errno.h>
/**********************************************************************
"(C) 1999",
};
+//#define fs_print(format,args...) g_print(format, ## args)
+#define fs_print(format,args...)
+
#define GST_TYPE_FILESRC \
(gst_filesrc_get_type())
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 {
ARG_BLOCKSIZE,
ARG_OFFSET,
ARG_MAPSIZE,
+ ARG_TOUCH,
};
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;
src->map_regions = g_tree_new(gst_filesrc_bufcmp);
src->map_regions_lock = g_mutex_new();
+
+ src->seek_happened = FALSE;
}
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;
}
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;
{
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);
}
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);
}
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);
{
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;
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
if (readend > src->filelen) {
readsize = src->filelen - src->curoffset;
readend = src->curoffset;
- eof = TRUE;
}
// if the start is past the mapstart
// 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);
}
// 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
*(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;
{
g_return_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN));
+ g_print ("close\n");
/* close the file */
close (src->fd);
} else if (data == SEEK_END) {
src->curoffset = src->filelen - (guint64)location;
}
+ src->seek_happened = TRUE;
// push a discontinuous event?
return TRUE;
}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ * 2001 Steve Baker <stevebaker_org@yahoo.co.uk>
+ *
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gstsinesrc.h>
+
+
+GstElementDetails gst_sinesrc_details = {
+ "Sine-wave src",
+ "Source/Audio",
+ "Create a sine wave of a given frequency and volume",
+ VERSION,
+ "Erik Walthinsen <omega@cse.ogi.edu>",
+ "(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;
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <config.h>
+#include <gst/gst.h>
+
+#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__ */
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);
}
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;
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);
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");
--- /dev/null
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+*.xml
+test1
+test2
--- /dev/null
+noinst_PROGRAMS = test1 test2
+
+test1_SOURCES = test1.c gstbuffer.c gstmempool.c
+
+#LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
--- /dev/null
+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
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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);
+}
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <gst/gstdata.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ATOMIC_H
+#include <asm/atomic.h>
+#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 <gst/gstbufferpool.h>
+
+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__ */
--- /dev/null
+#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
+}
--- /dev/null
+#include <glib.h>
+
+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);
--- /dev/null
+#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;
+}
--- /dev/null
+#include <gst/gst.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;
+}
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);
--- /dev/null
+noinst_PROGRAMS = seek
+
+LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
--- /dev/null
+#include <gst/gst.h>
+
+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;
+}
gst_element_set_state (pipeline, GST_STATE_PLAYING);
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("xmlTest.gst", gst_xml_write (GST_ELEMENT (pipeline)));
+#endif
}
--- /dev/null
+noinst_PROGRAMS = gmemchunktest gstmemchunktest
+
+gmemchunktest_SOURCES = gmemchunktest.c
+gstmemchunktest_SOURCES = gstmemchunktest.c gstmemchunk.c gstmemchunk.h
+
+LIBS += $(GST_LIBS)
+CFLAGS += $(GST_CFLAGS)
--- /dev/null
+#include <gst/gst.h>
+
+#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<num_allocs; i++) {
+ chunk = alloc_chunk ();
+ free_chunk (chunk);
+ }
+
+ pthread_exit(NULL);
+}
+
+
+gint
+main (gint argc, gchar *argv[])
+{
+ pthread_t threads[MAX_THREADS];
+ int rc, t;
+
+ gst_init (&argc, &argv);
+
+ if (argc != 3) {
+ g_print ("usage: %s <num_threads> <num_allocs>\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();
+}
--- /dev/null
+#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));
+}
--- /dev/null
+
+#include <gst/gst.h>
+
+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);
--- /dev/null
+#include <gst/gst.h>
+#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<num_allocs; i++) {
+ chunk = alloc_chunk ();
+ free_chunk (chunk);
+ }
+
+ pthread_exit(NULL);
+}
+
+
+gint
+main (gint argc, gchar *argv[])
+{
+ pthread_t threads[MAX_THREADS];
+ int rc, t;
+
+ gst_init (&argc, &argv);
+
+ if (argc != 3) {
+ g_print ("usage: %s <num_threads> <num_allocs>\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;
+}
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) {
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
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 \
gst_element_set_state (pipeline, GST_STATE_PLAYING);
+#ifndef GST_DISABLE_LOADSAVE
xmlSaveFile("xmlTest.gst", gst_xml_write (GST_ELEMENT (pipeline)));
+#endif
}
gboolean
}
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);
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);
--- /dev/null
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+test1
--- /dev/null
+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)
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <gst/gst.h>
+#include <libs/bytestream/gstbytestream.h>
+
+#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 <omega@temple-baptist.com>," "Wim Taymans <wim.taymans@chello.be>",
+ "(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);
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+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;
+}
--- /dev/null
+int vmsize();
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+
+#include <gst/gst.h>
+#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; i<GST_BUFFER_SIZE (buf); i++) {
+ if (*ptr++ != count++) {
+ g_print ("data error!\n");
+ return;
+ }
+ }
+ }
+ }
+ else {
+ g_print ("not a buffer ! %p\n", buf);
+ }
+}
+static gchar*
+create_desc (TestParam *param)
+{
+ gchar *desc;
+
+ desc = g_strdup_printf ("%s %s, pattern %s", (param->src_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] <paramfile> <iterations>\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;
+
+}
--- /dev/null
+# 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
+# <action><size>[:<action><size>...]
+#
+# <action> can be:
+# r = read
+# p = peek
+# pb = peek bytes
+# f = flush
+# <size> can be:
+# <empty> = fixed size
+# r = random size
+# < = previous size
+# <int> = 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
+if GST_DISABLE_LOADSAVE
+noinst_PROGRAMS =
+else
noinst_PROGRAMS = runxml
+endif
# nothing but apps here, this is safe
LIBS += $(GST_LIBS)
--- /dev/null
+Makefile
+Makefile.in
+*.o
+*.lo
+*.la
+.deps
+.libs
+test1
--- /dev/null
+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)
--- /dev/null
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ * 2000 Wim Taymans <wtay@chello.be>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <gst/gst.h>
+#include <libs/bytestream/gstbytestream.h>
+
+#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 <omega@temple-baptist.com>," "Wim Taymans <wim.taymans@chello.be>",
+ "(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);
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+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;
+}
--- /dev/null
+int vmsize();
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+
+#include <gst/gst.h>
+#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; i<GST_BUFFER_SIZE (buf); i++) {
+ if (*ptr++ != count++) {
+ g_print ("data error!\n");
+ return;
+ }
+ }
+ }
+ }
+ else {
+ g_print ("not a buffer ! %p\n", buf);
+ }
+}
+static gchar*
+create_desc (TestParam *param)
+{
+ gchar *desc;
+
+ desc = g_strdup_printf ("%s %s, pattern %s", (param->src_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] <paramfile> <iterations>\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;
+
+}
--- /dev/null
+# 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
+# <action><size>[:<action><size>...]
+#
+# <action> can be:
+# r = read
+# p = peek
+# pb = peek bytes
+# f = flush
+# <size> can be:
+# <empty> = fixed size
+# r = random size
+# < = previous size
+# <int> = 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
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
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)
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
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
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);