mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 11:10:37 +00:00
merge from EVENTS1 on 20011016
Original commit message from CVS: merge from EVENTS1 on 20011016
This commit is contained in:
parent
b81c9eb858
commit
d574ab8126
135 changed files with 10416 additions and 3922 deletions
10
autogen.sh
10
autogen.sh
|
@ -191,10 +191,14 @@ automake --add-missing || {
|
|||
# now remove the cache, because it can be considered dangerous in this case
|
||||
rm -f config.cache
|
||||
|
||||
# The new configure options for busy application developers (Hadess)
|
||||
#./configure --enable-maintainer-mode --enable-debug --enable-DEBUG "$@" || {
|
||||
CONFIGURE_OPT='--enable-maintainer-mode --enable-plugin-builddir --enable-debug --enable-DEBUG'
|
||||
|
||||
./configure --enable-maintainer-mode --enable-plugin-builddir --enable-debug --enable-DEBUG "$@" || {
|
||||
echo
|
||||
echo "./configure default flags: $CONFIGURE_OPT"
|
||||
echo "using: $CONFIGURE_OPT $@"
|
||||
echo
|
||||
|
||||
./configure $CONFIGURE_OPT "$@" || {
|
||||
echo
|
||||
echo "configure failed"
|
||||
exit 1
|
||||
|
|
|
@ -216,13 +216,6 @@ GST_CHECK_FEATURE(GLIB2, [use of glib-2.0 and GObject], , [
|
|||
])
|
||||
AC_SUBST(USE_GLIB2)
|
||||
|
||||
dnl FIXME: check for gtk2 and gnome2 - these conditionals are currently
|
||||
dnl always false.
|
||||
AM_CONDITIONAL(USE_GTK2, test "x$USE_GTK2" = "xyes")
|
||||
AC_SUBST(USE_GTK2)
|
||||
AM_CONDITIONAL(USE_GNOME2, test "x$USE_GNOME2" = "xyes")
|
||||
AC_SUBST(USE_GNOME2)
|
||||
|
||||
if test x$USE_GLIB2 = xno; then
|
||||
dnl Check for glib and gtk
|
||||
AM_PATH_GLIB(1.2.0,,
|
||||
|
@ -230,11 +223,24 @@ if test x$USE_GLIB2 = xno; then
|
|||
glib gmodule gthread)
|
||||
AM_PATH_GTK(1.2.0,,
|
||||
AC_MSG_ERROR(Cannot find gtk: Is gtk-config in path?))
|
||||
HAVE_GTK=yes
|
||||
|
||||
CORE_LIBS="$CORE_LIBS $GLIB_LIBS $GTK_LIBS"
|
||||
CORE_CFLAGS="$CORE_CFLAGS $GLIB_CFLAGS $GTK_CFLAGS"
|
||||
else
|
||||
PKG_CHECK_MODULES(GTK2, gtk+-2.0, HAVE_GTK=yes, HAVE_GTK=no)
|
||||
|
||||
GTK_FLAGS=$GTK2_CFLAGS
|
||||
GTK_LIBS=$GTK2_LIBS
|
||||
|
||||
dnl FIXME: check for gnome2 - this conditional is currently
|
||||
dnl always false.
|
||||
AM_CONDITIONAL(USE_GNOME2, test "x$USE_GNOME2" = "xyes")
|
||||
AC_SUBST(USE_GNOME2)
|
||||
fi
|
||||
|
||||
AC_SUBST(GTK_LIBS)
|
||||
AC_SUBST(GTK_CFLAGS)
|
||||
|
||||
dnl Check for libxml
|
||||
AC_PATH_PROG(XML_CONFIG, xml-config, no)
|
||||
|
@ -926,12 +932,16 @@ if test "x$USE_DEBUG" = xyes; then
|
|||
fi
|
||||
|
||||
if test "x$USE_PROFILING" = xyes; then
|
||||
CFLAGS="$CFLAGS -pg"
|
||||
CFLAGS="$CFLAGS -pg -fprofile-arcs"
|
||||
FOMIT_FRAME_POINTER=""
|
||||
else
|
||||
FOMIT_FRAME_POINTER="-fomit-frame-pointer"
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl AC_SUBST(FOMIT_FRAME_POINTER)
|
||||
dnl
|
||||
|
||||
if test "x$HAVE_LIBXV" = xyes; then
|
||||
AC_DEFINE(HAVE_LIBXV)
|
||||
fi
|
||||
|
@ -1024,6 +1034,7 @@ AM_CONDITIONAL(HAVE_NASM, test "x$HAVE_NASM" = "xyes")
|
|||
AM_CONDITIONAL(HAVE_LIBGLADE_GNOME, test "x$HAVE_LIBGLADE_GNOME" = "xyes")
|
||||
AM_CONDITIONAL(HAVE_GNOME, test "x$HAVE_GNOME" = "xyes")
|
||||
AM_CONDITIONAL(HAVE_LIBXV, test "x$HAVE_LIBXV" = "xyes")
|
||||
AM_CONDITIONAL(HAVE_GTK, test "x$HAVE_GTK" = "xyes")
|
||||
AM_CONDITIONAL(HAVE_GTK_DOC, $HAVE_GTK_DOC)
|
||||
AM_CONDITIONAL(BUILD_DOCS, test "x$BUILD_DOCS" = "xyes")
|
||||
AM_CONDITIONAL(BUILD_TESTS, test "x$BUILD_TESTS" = "xyes")
|
||||
|
@ -1176,6 +1187,7 @@ libs/getbits/Makefile
|
|||
libs/putbits/Makefile
|
||||
libs/idct/Makefile
|
||||
libs/audio/Makefile
|
||||
libs/bytestream/Makefile
|
||||
libs/control/Makefile
|
||||
plugins/Makefile
|
||||
plugins/a52dec/Makefile
|
||||
|
@ -1285,6 +1297,8 @@ test/Makefile
|
|||
test/xml/Makefile
|
||||
test/bindings/Makefile
|
||||
dnl someone should fix this test/misc/Makefile
|
||||
test/memchunk/Makefile
|
||||
test/events/Makefile
|
||||
tests/Makefile
|
||||
tests/sched/Makefile
|
||||
tests/eos/Makefile
|
||||
|
|
|
@ -116,7 +116,7 @@ The type of the autoplugger.
|
|||
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@feature:
|
||||
@longdesc:
|
||||
@type:
|
||||
|
||||
|
@ -207,22 +207,3 @@ The type of the autoplugger.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_autoplugfactory_save_thyself ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@factory:
|
||||
@parent:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_autoplugfactory_load_thyself ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@parent:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
|
|
@ -239,6 +239,7 @@ used when data in a stream has been skipped
|
|||
|
||||
</para>
|
||||
|
||||
@data_type:
|
||||
@lock:
|
||||
@data:
|
||||
@size:
|
||||
|
@ -265,6 +266,8 @@ used when data in a stream has been skipped
|
|||
</para>
|
||||
|
||||
@pool:
|
||||
@location:
|
||||
@size:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
@ -293,9 +296,12 @@ used when data in a stream has been skipped
|
|||
|
||||
</para>
|
||||
|
||||
@buf:
|
||||
@buf2:
|
||||
@Returns:
|
||||
<!-- # Unused Parameters # -->
|
||||
@buffer:
|
||||
@append:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_buffer_ref ##### -->
|
||||
|
|
|
@ -52,30 +52,10 @@ A bufferpool can be requested from a pad with the gst_pad_get_bufferpool() funct
|
|||
</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>
|
||||
|
@ -85,24 +65,6 @@ the pool.
|
|||
@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>
|
||||
|
||||
|
@ -130,26 +92,6 @@ the pool.
|
|||
@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>
|
||||
|
||||
|
@ -163,9 +105,10 @@ the pool.
|
|||
|
||||
</para>
|
||||
|
||||
@oldpool:
|
||||
@buffer_size:
|
||||
@pool_size:
|
||||
@Returns:
|
||||
<!-- # Unused Parameters # -->
|
||||
@oldpool:
|
||||
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@ Specify how many bytes to read at a time.
|
|||
Get/set the current offset in the file.
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstDiskSrc:size ##### -->
|
||||
<!-- ##### ARG GstDiskSrc:filesize ##### -->
|
||||
<para>
|
||||
Get the size of the file.
|
||||
|
||||
</para>
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ of the element, the GtkType value for it, as well as a pointer to the
|
|||
GstElementDetails struct for the element.
|
||||
</para>
|
||||
|
||||
@name:
|
||||
@feature:
|
||||
@type:
|
||||
@details:
|
||||
@padtemplates:
|
||||
|
@ -241,14 +241,6 @@ circumstances.
|
|||
@element: The element in question.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_element_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### MACRO gst_element_destroy ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -503,14 +495,6 @@ circumstances.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_elementfactory_destroy ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@elementfactory:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_elementfactory_add_padtemplate ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -580,25 +564,6 @@ circumstances.
|
|||
@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
|
||||
|
|
|
@ -24,7 +24,7 @@ with the buffer. (fakesink)
|
|||
@gstfakesink: the object which received the signal.
|
||||
@arg1:
|
||||
|
||||
<!-- ##### ARG GstFakeSink:num_sinks ##### -->
|
||||
<!-- ##### ARG GstFakeSink:num-sinks ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
|
|
@ -22,12 +22,12 @@ The <classname>GstFakeSrc</classname> generates empty buffers. (fakesrc)
|
|||
@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>
|
||||
|
@ -42,7 +42,7 @@ The <classname>GstFakeSrc</classname> generates empty buffers. (fakesrc)
|
|||
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstFakeSrc:num_buffers ##### -->
|
||||
<!-- ##### ARG GstFakeSrc:num-buffers ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
|
|
@ -22,12 +22,12 @@ Pass data without modification.
|
|||
@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>
|
||||
|
|
|
@ -141,14 +141,6 @@ Check if the object has been destroyed.
|
|||
@obj: The Object to check
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_object_new ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_object_check_uniqueness ##### -->
|
||||
<para>
|
||||
|
||||
|
|
|
@ -189,24 +189,6 @@ a start/stop timecode pair.
|
|||
@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
|
||||
|
@ -247,25 +229,6 @@ The function that will be called when negotiating.
|
|||
@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.
|
||||
|
@ -383,24 +346,6 @@ Destroy the pad.
|
|||
@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>
|
||||
|
||||
|
@ -627,32 +572,6 @@ Destroy the pad.
|
|||
@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>
|
||||
|
||||
|
@ -706,15 +625,6 @@ Call the EOS function of the pad
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_pad_eos_func ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@pad:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### STRUCT GstRealPad ##### -->
|
||||
<para>
|
||||
|
||||
|
@ -731,12 +641,12 @@ Call the EOS function of the pad
|
|||
@len:
|
||||
@sched:
|
||||
@chainfunc:
|
||||
@chainhandler:
|
||||
@getfunc:
|
||||
@gethandler:
|
||||
@eventfunc:
|
||||
@eventhandler:
|
||||
@getregionfunc:
|
||||
@qosfunc:
|
||||
@eosfunc:
|
||||
@pushfunc:
|
||||
@pullfunc:
|
||||
@pullregionfunc:
|
||||
@negotiatefunc:
|
||||
@newcapsfunc:
|
||||
|
@ -831,22 +741,6 @@ Get the getregion function of the real pad.
|
|||
@pad: the real pad to query.
|
||||
|
||||
|
||||
<!-- ##### 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.
|
||||
|
@ -855,22 +749,6 @@ 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.
|
||||
|
|
|
@ -63,11 +63,9 @@ to bring it into memory.
|
|||
@name:
|
||||
@longname:
|
||||
@filename:
|
||||
@types:
|
||||
@numtypes:
|
||||
@elements:
|
||||
@numelements:
|
||||
@numautopluggers:
|
||||
@features:
|
||||
@numfeatures:
|
||||
@module:
|
||||
|
||||
<!-- ##### USER_FUNCTION GstPluginInitFunc ##### -->
|
||||
<para>
|
||||
|
@ -198,33 +196,6 @@ loaded will use this variable to initialize the plugin.
|
|||
@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>
|
||||
|
||||
|
@ -242,59 +213,6 @@ loaded will use this variable to initialize the plugin.
|
|||
@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>
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ The queue blocks by default.
|
|||
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.
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,7 +14,7 @@ A tee can be used to split out the filter graph.
|
|||
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG GstTee:num_pads ##### -->
|
||||
<!-- ##### ARG GstTee:num-pads ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
|
|
@ -45,7 +45,7 @@ Thread flags:
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### ARG GstThread:create_thread ##### -->
|
||||
<!-- ##### ARG GstThread:create-thread ##### -->
|
||||
<para>
|
||||
TRUE if the thread should be created.
|
||||
|
||||
|
|
|
@ -71,13 +71,14 @@ A type.
|
|||
@id:
|
||||
@mime:
|
||||
@exts:
|
||||
@typefindfuncs:
|
||||
@factories:
|
||||
|
||||
<!-- ##### STRUCT GstTypeFactory ##### -->
|
||||
<para>
|
||||
The struct with the typefactory information.
|
||||
</para>
|
||||
|
||||
@feature:
|
||||
@mime:
|
||||
@exts:
|
||||
@typefindfunc:
|
||||
|
@ -126,22 +127,3 @@ The struct with the typefactory information.
|
|||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_typefactory_load_thyself ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@parent:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gst_typefactory_save_thyself ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@factory:
|
||||
@parent:
|
||||
@Returns:
|
||||
|
||||
|
||||
|
|
|
@ -1,140 +1,138 @@
|
|||
some random ramblings about the event system:
|
||||
This is a round up from our IRC session on events. It's open for
|
||||
discussion of course.
|
||||
|
||||
Possible candidates for events
|
||||
Definition
|
||||
----------
|
||||
|
||||
The event system is designed to be a mechanism for _inter_plugin_
|
||||
communication. Their scope is therefore limited in a way that they do
|
||||
not serve as a way to communicate between plugins and the app (signals
|
||||
and properties are still used for plugin-app communication).
|
||||
|
||||
Events will be generated by either a plugin or the app. It should be
|
||||
possible for a plugin to generate an event on one of its pads and it
|
||||
should be possible for an app to insert an event on an abitrary pad in
|
||||
the pipeline.
|
||||
|
||||
|
||||
Event handling
|
||||
--------------
|
||||
|
||||
Events can both travel upstream or downstream. Some events, by nature,
|
||||
only travel in one direction.
|
||||
|
||||
* downstream events
|
||||
|
||||
- Travel in the same way buffers do. This includes that they are handled
|
||||
by the scheduler. The rationale is that the events should be kept
|
||||
as close to the buffers are possible.
|
||||
|
||||
- plugins should check the type of the GstData passed in the _chain
|
||||
or _loop function and act appropriatly. This can be done by either
|
||||
doing their own stuff or by calling the default handler.
|
||||
|
||||
- are handled on the sink pad.
|
||||
|
||||
* upstream events
|
||||
|
||||
- are handled with an event handler attached to the srcpad. A default
|
||||
handler will be implemented for pads that don't implement their own
|
||||
handler.
|
||||
|
||||
- travel as fast as possible. the rationale is that a seek event should
|
||||
get to the src element ASAP.
|
||||
|
||||
|
||||
Possible candidates for events
|
||||
------------------------------
|
||||
|
||||
- QoS
|
||||
quality of service. Plugins can notify other plugins about the quality
|
||||
of the pipeline. A video element can for example say that it receives
|
||||
too much frames and that plugins connected to it need to slow down.
|
||||
|
||||
- EOS
|
||||
A plugin can notify other plugins that it has run out-of-data.
|
||||
|
||||
- Seek
|
||||
- caps nego??
|
||||
- bufferpool get??
|
||||
Used to notify plugins that they need to seek to a certain byte offset
|
||||
or timestamp.
|
||||
|
||||
- discontinuous
|
||||
A plugin has detected a discontinuity in the stream. Other plugins
|
||||
might need to resync.
|
||||
|
||||
- flush
|
||||
Plugins need to get rid of any buffered data ASAP.
|
||||
|
||||
- caps nego??
|
||||
- bufferpool get??
|
||||
- ...
|
||||
|
||||
Assumptions for events
|
||||
----------------------
|
||||
|
||||
- They are tied to a pad.
|
||||
- get rid of gst_pad_set_*_function (except for the chain/get ones)
|
||||
- occur async to dataflow. (need locking?)
|
||||
- fixed set of events only for core features. (elements cannot abuse
|
||||
events for doing dataflow)
|
||||
application generated events
|
||||
----------------------------
|
||||
|
||||
Questions
|
||||
The application can insert events into the pipeline at arbirary
|
||||
places. This will be done by calling gst_pad_event() on a pad.
|
||||
|
||||
A first implementation will only cover inserting events on src pads
|
||||
since inserting events on sinkpads needs changes to the scheduler.
|
||||
|
||||
|
||||
Effects of events on plugins
|
||||
----------------------------
|
||||
|
||||
some events are going to change the state of an element. The EOS event
|
||||
will for example change the state of an element to the PAUSED state. Not
|
||||
sure when or how this will happen.
|
||||
|
||||
|
||||
use cases
|
||||
---------
|
||||
|
||||
limit the valid directions an event can travel in? ie. Can EOS only
|
||||
travel downstream (left to right)?
|
||||
1) filesrc ! fakesink
|
||||
|
||||
eg. Seek travels upstream, but it makes sense to also make it travel
|
||||
downstream (the case of a disksink, where we overwrite the header)
|
||||
filesrc will read until it reaches EOF. It will then create a GstEvent
|
||||
of type EOS and return it in the _get function. The event will travel
|
||||
downstream and will reach the fakesink element. Fakesink will detect
|
||||
the event in the _chain function and will call the default handler. The
|
||||
default handler will set the element to the paused state. filesrc will
|
||||
eventually change its state to PAUSED, probably before sending out the
|
||||
event (TBD)
|
||||
|
||||
2) filesrc ! fakesink
|
||||
|
||||
The app wants to perform a seek on filesrc. It'll call the gst_pad_event()
|
||||
on filesrcs src pad with the SEEK event type. The event handler will
|
||||
react and change filesrcs internal status. filesrc will return a DISCONT
|
||||
event before returning the buffer with the new offset.
|
||||
|
||||
3) filesrc ! mpeg2parse video_0! queue ! { mpeg2dec ! xvideosink }
|
||||
|
||||
lost of possibilities here: The app can choose to insert a seek event
|
||||
on the filesrc element (byte offset), it can insert a byte/time offset
|
||||
seek on the video_0 pad of mpeg2parse or it can insert a time seek event
|
||||
on mpeg2decs src pad.
|
||||
|
||||
the event will travel upstream using the handlers and the intermediate
|
||||
elements can convert the event from a time to a byte offset (possibly
|
||||
using GstTimeCache to speed up things).
|
||||
|
||||
Filesrc will get a byte seek event on its src pad and will proceed as
|
||||
in case 2.
|
||||
|
||||
As can be seen from this example the app will generate an event in another
|
||||
context than those of the plugins, so this will need proper locking.
|
||||
|
||||
The app can also choose to insert a flush event on one of the src
|
||||
pads. The plugins would clear their cached data and forward the event
|
||||
to their upstream peer pad(s).
|
||||
|
||||
4)...
|
||||
|
||||
Insert impossible case here..
|
||||
|
||||
|
||||
Setting an event function
|
||||
-------------------------
|
||||
|
||||
void gst_pad_set_event_function (GstPad *pad, gint event_mask,
|
||||
GstEventFunction *function);
|
||||
|
||||
|
||||
event masks:
|
||||
|
||||
typedef enum {
|
||||
GST_EVENT_EOS = (1 << 0),
|
||||
GST_EVENT_QOS = (1 << 1),
|
||||
GST_EVENT_SEEK = (1 << 2),
|
||||
GST_EVENT_CAPS = (1 << 3),
|
||||
} GstEventType;
|
||||
|
||||
Event structure
|
||||
---------------
|
||||
|
||||
typedef struct {
|
||||
GstEventType type;
|
||||
GstEventMinorType minor;
|
||||
guint64 timestamp; /* also sequence number ?? */
|
||||
|
||||
union {
|
||||
/* EOS stuff */
|
||||
/* QoS stuff */
|
||||
/* Seek stuff */
|
||||
GstSeekType type; /* time, bytes, ... */
|
||||
gint64 offset;
|
||||
gint64 lenth;
|
||||
/* Caps stuff */
|
||||
GstCaps *caps;
|
||||
} data;
|
||||
} GstEvent;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GST_EVENT_MINOR_NONE,
|
||||
/* EOS stuff */
|
||||
|
||||
/* QoS stuff */
|
||||
/* Seek stuff */
|
||||
GST_EVENT_MINOR_OFFSET,
|
||||
GST_EVENT_MINOR_TIME,
|
||||
|
||||
/* caps nego stuff */
|
||||
GST_EVENT_MINOR_CAPS_TRY,
|
||||
GST_EVENT_MINOR_CAPS_START,
|
||||
GST_EVENT_MINOR_CAPS_FINAL,
|
||||
} GstEventMinorType;
|
||||
|
||||
|
||||
Receiving events
|
||||
----------------
|
||||
|
||||
a sample GstEventFunction, the event functions returns TRUE if the event is handled,
|
||||
FALSE otherwise.
|
||||
|
||||
gboolean
|
||||
gst_anelement_handle_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
if (event->type == GST_EVENT_EOS) {
|
||||
/* do something */
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == GST_EVENT_CAPS) {
|
||||
if (event->minor == GST_EVENT_CAPS_TRY) {
|
||||
/* try using this caps structure */
|
||||
return TRUE; /* return FALSE to proxy ???*/
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Default event handler for pads
|
||||
------------------------------
|
||||
|
||||
gboolean
|
||||
gst_pad_handle_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
GstElement *element;
|
||||
GList *pads;
|
||||
GstPad *srcpad;
|
||||
gboolean result = TRUE;
|
||||
GstPadDirection dir = GST_PAD_DIRECTION (pad);
|
||||
|
||||
g_return_val_if_fail (pad != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
|
||||
|
||||
element = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (pad)));
|
||||
|
||||
/* send out the events to all pad with opposite direction */
|
||||
pads = gst_element_get_pad_list(element);
|
||||
while (pads) {
|
||||
otherpad = GST_PAD(pads->data);
|
||||
pads = g_list_next(pads);
|
||||
|
||||
if (gst_pad_get_direction(otherpad) != dir) {
|
||||
result &= gst_pad_send_event (GST_REAL_PAD(otherpad), event);
|
||||
}
|
||||
}
|
||||
|
||||
/* result is combined result of all handlers? */
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
140
docs/random/wtay/events2
Normal file
140
docs/random/wtay/events2
Normal file
|
@ -0,0 +1,140 @@
|
|||
some random ramblings about the event system:
|
||||
|
||||
Possible candidates for events
|
||||
------------------------------
|
||||
|
||||
- QoS
|
||||
- EOS
|
||||
- Seek
|
||||
- caps nego??
|
||||
- bufferpool get??
|
||||
- ...
|
||||
|
||||
Assumptions for events
|
||||
----------------------
|
||||
|
||||
- They are tied to a pad.
|
||||
- get rid of gst_pad_set_*_function (except for the chain/get ones)
|
||||
- occur async to dataflow. (need locking?)
|
||||
- fixed set of events only for core features. (elements cannot abuse
|
||||
events for doing dataflow)
|
||||
|
||||
Questions
|
||||
---------
|
||||
|
||||
limit the valid directions an event can travel in? ie. Can EOS only
|
||||
travel downstream (left to right)?
|
||||
|
||||
eg. Seek travels upstream, but it makes sense to also make it travel
|
||||
downstream (the case of a disksink, where we overwrite the header)
|
||||
|
||||
|
||||
Setting an event function
|
||||
-------------------------
|
||||
|
||||
void gst_pad_set_event_function (GstPad *pad, gint event_mask,
|
||||
GstEventFunction *function);
|
||||
|
||||
|
||||
event masks:
|
||||
|
||||
typedef enum {
|
||||
GST_EVENT_EOS = (1 << 0),
|
||||
GST_EVENT_QOS = (1 << 1),
|
||||
GST_EVENT_SEEK = (1 << 2),
|
||||
GST_EVENT_CAPS = (1 << 3),
|
||||
} GstEventType;
|
||||
|
||||
Event structure
|
||||
---------------
|
||||
|
||||
typedef struct {
|
||||
GstEventType type;
|
||||
GstEventMinorType minor;
|
||||
guint64 timestamp; /* also sequence number ?? */
|
||||
|
||||
union {
|
||||
/* EOS stuff */
|
||||
/* QoS stuff */
|
||||
/* Seek stuff */
|
||||
GstSeekType type; /* time, bytes, ... */
|
||||
gint64 offset;
|
||||
gint64 lenth;
|
||||
/* Caps stuff */
|
||||
GstCaps *caps;
|
||||
} data;
|
||||
} GstEvent;
|
||||
|
||||
|
||||
typedef enum {
|
||||
GST_EVENT_MINOR_NONE,
|
||||
/* EOS stuff */
|
||||
|
||||
/* QoS stuff */
|
||||
/* Seek stuff */
|
||||
GST_EVENT_MINOR_OFFSET,
|
||||
GST_EVENT_MINOR_TIME,
|
||||
|
||||
/* caps nego stuff */
|
||||
GST_EVENT_MINOR_CAPS_TRY,
|
||||
GST_EVENT_MINOR_CAPS_START,
|
||||
GST_EVENT_MINOR_CAPS_FINAL,
|
||||
} GstEventMinorType;
|
||||
|
||||
|
||||
Receiving events
|
||||
----------------
|
||||
|
||||
a sample GstEventFunction, the event functions returns TRUE if the event is handled,
|
||||
FALSE otherwise.
|
||||
|
||||
gboolean
|
||||
gst_anelement_handle_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
if (event->type == GST_EVENT_EOS) {
|
||||
/* do something */
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == GST_EVENT_CAPS) {
|
||||
if (event->minor == GST_EVENT_CAPS_TRY) {
|
||||
/* try using this caps structure */
|
||||
return TRUE; /* return FALSE to proxy ???*/
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Default event handler for pads
|
||||
------------------------------
|
||||
|
||||
gboolean
|
||||
gst_pad_handle_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
GstElement *element;
|
||||
GList *pads;
|
||||
GstPad *srcpad;
|
||||
gboolean result = TRUE;
|
||||
GstPadDirection dir = GST_PAD_DIRECTION (pad);
|
||||
|
||||
g_return_val_if_fail (pad != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_REAL_PAD(pad), FALSE); // NOTE the restriction
|
||||
|
||||
element = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (pad)));
|
||||
|
||||
/* send out the events to all pad with opposite direction */
|
||||
pads = gst_element_get_pad_list(element);
|
||||
while (pads) {
|
||||
otherpad = GST_PAD(pads->data);
|
||||
pads = g_list_next(pads);
|
||||
|
||||
if (gst_pad_get_direction(otherpad) != dir) {
|
||||
result &= gst_pad_send_event (GST_REAL_PAD(otherpad), event);
|
||||
}
|
||||
}
|
||||
|
||||
/* result is combined result of all handlers? */
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +120,7 @@ gst_editor_project_new (void)
|
|||
GstEditorProject *
|
||||
gst_editor_project_new_from_file (const guchar *fname)
|
||||
{
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
GstEditorProject *editorproject;
|
||||
GstXML *xml;
|
||||
GList *elements;
|
||||
|
@ -140,8 +141,10 @@ gst_editor_project_new_from_file (const guchar *fname)
|
|||
|
||||
elements = g_list_next (elements);
|
||||
}
|
||||
|
||||
return editorproject;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -162,7 +165,9 @@ gst_editor_project_save_as (GstEditorProject *project, const guchar *fname)
|
|||
while (elements) {
|
||||
GstElement *element = (GstElement *) elements->data;
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlSaveFile (fname, gst_xml_write (element));
|
||||
#endif
|
||||
|
||||
elements = g_list_next (elements);
|
||||
}
|
||||
|
|
|
@ -5,10 +5,16 @@ else
|
|||
GNOME_SUBDS =
|
||||
endif
|
||||
|
||||
SUBDIRS = $(GNOME_SUBDS) \
|
||||
if GST_DISABLE_LOADSAVE
|
||||
GST_LOADSAVE_DIRS =
|
||||
else
|
||||
GST_LOADSAVE_DIRS = xml typefind
|
||||
endif
|
||||
|
||||
SUBDIRS = $(GNOME_SUBDS) $(GST_LOADSAVE_DIRS) \
|
||||
helloworld helloworld2 \
|
||||
queue queue2 queue3 queue4 \
|
||||
launch thread xml plugins typefind mixer cutter
|
||||
launch thread plugins mixer cutter
|
||||
|
||||
DIST_SUBDIRS = autoplug \
|
||||
helloworld helloworld2 \
|
||||
|
|
|
@ -94,7 +94,9 @@ gst_play_have_type (GstElement *typefind, GstCaps *caps, GstElement *pipeline)
|
|||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlSaveFile("xmlTest.gst", gst_xml_write (GST_ELEMENT (pipeline)));
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
|
@ -182,7 +182,9 @@ int main(int argc,char *argv[])
|
|||
}
|
||||
env_register_cp (channel_in->volenv, num_channels * 10.0 , 1.0 / num_channels); /* to end level */
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlSaveFile("mixer.xml", gst_xml_write(GST_ELEMENT(main_bin)));
|
||||
#endif
|
||||
|
||||
/* start playing */
|
||||
gst_element_set_state(main_bin, GST_STATE_PLAYING);
|
||||
|
@ -356,7 +358,9 @@ create_input_channel (int id, char* location)
|
|||
gst_element_get_pad (decoder, "src"), "src_00");
|
||||
|
||||
#endif
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlSaveFile ("mixer.gst", gst_xml_write (new_element));
|
||||
#endif
|
||||
|
||||
gst_bin_add (GST_BIN(channel->pipe), channel->volenv);
|
||||
gst_bin_add (GST_BIN (channel->pipe), new_element);
|
||||
|
|
|
@ -8,6 +8,8 @@ else
|
|||
GSTARCH_SRCS =
|
||||
endif
|
||||
|
||||
#GST_INSTRUMENT_FLAGS = -finstrument-functions -DGST_ENABLE_FUNC_INSTRUMENTATION
|
||||
|
||||
if USE_GLIB2
|
||||
GST_OBJECT_MODEL_SRC = gstmarshal.c
|
||||
GST_OBJECT_MODEL_HDR = gstmarshal.h
|
||||
|
@ -67,6 +69,7 @@ libgst_la_SOURCES = \
|
|||
gstcpu.c \
|
||||
gstelement.c \
|
||||
gstelementfactory.c \
|
||||
gstevent.c \
|
||||
gstextratypes.c \
|
||||
gstinfo.c \
|
||||
gstpad.c \
|
||||
|
@ -154,6 +157,7 @@ libgstincludedir = $(includedir)/gst
|
|||
libgstinclude_HEADERS = \
|
||||
cothreads.h \
|
||||
gst.h \
|
||||
gstconfig.h \
|
||||
$(GST_OBJECT_MODEL_HDR) \
|
||||
gstobject.h \
|
||||
gsttypes.h \
|
||||
|
@ -164,6 +168,7 @@ libgstinclude_HEADERS = \
|
|||
gstcaps.h \
|
||||
gstclock.h \
|
||||
gstcpu.h \
|
||||
gstdata.h \
|
||||
gstelement.h \
|
||||
gstevent.h \
|
||||
gstextratypes.h \
|
||||
|
@ -203,6 +208,7 @@ CFLAGS = \
|
|||
-Wnested-externs \
|
||||
-Winline -Wno-unused
|
||||
|
||||
CFLAGS = $(LIBGST_CFLAGS) -D_GNU_SOURCE -DGST_CONFIG_DIR=\""$(GST_CONFIG_DIR)"\" -Wall
|
||||
LIBS = $(LIBGST_LIBS)
|
||||
LDFLAGS = ""
|
||||
libgst_la_LDFLAGS = -version-info $(GST_LIBVERSION)
|
||||
|
|
|
@ -430,7 +430,7 @@ gst_autoplugger_cache_empty(GstElement *element, GstAutoplugger *autoplugger)
|
|||
// try to PLAY the whole thing
|
||||
gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING);
|
||||
|
||||
xmlSaveFile("autoplugger.gst", gst_xml_write(GST_ELEMENT_SCHED(autoplugger)->parent));
|
||||
// xmlSaveFile("autoplugger.gst", gst_xml_write(GST_ELEMENT_SCHED(autoplugger)->parent));
|
||||
|
||||
GST_INFO(GST_CAT_AUTOPLUG, "autoplugger_cache_empty finished");
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ else
|
|||
GSTHTTPSRC=
|
||||
endif
|
||||
|
||||
#CFLAGS += -O2 -Wall -finstrument-functions -DGST_ENABLE_FUNC_INSTRUMENTATION
|
||||
|
||||
libgstelements_la_DEPENDENCIES = ../libgst.la
|
||||
libgstelements_la_SOURCES = \
|
||||
gstelements.c \
|
||||
|
@ -37,8 +39,10 @@ noinst_HEADERS = \
|
|||
gstfdsink.h \
|
||||
gstpipefilter.h \
|
||||
gsttee.h \
|
||||
gstaggregator.h
|
||||
CFLAGS += -O2 -Wall
|
||||
gstaggregator.h \
|
||||
gstsinesrc.h
|
||||
|
||||
CFLAGS += -O2 -Wall
|
||||
LDFLAGS += -lm
|
||||
|
||||
libgstelements_la_LIBADD = $(GHTTP_LIBS)
|
||||
|
|
|
@ -76,7 +76,8 @@ gst_aggregator_sched_get_type (void)
|
|||
static void gst_aggregator_class_init (GstAggregatorClass *klass);
|
||||
static void gst_aggregator_init (GstAggregator *aggregator);
|
||||
|
||||
static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp);
|
||||
static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp, const
|
||||
gchar *unused);
|
||||
|
||||
static void gst_aggregator_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
|
@ -150,7 +151,7 @@ gst_aggregator_init (GstAggregator *aggregator)
|
|||
}
|
||||
|
||||
static GstPad*
|
||||
gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
||||
gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *sinkpad;
|
||||
|
|
|
@ -64,8 +64,8 @@ static void gst_disksrc_set_property (GObject *object, guint prop_id,
|
|||
static void gst_disksrc_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static GstBuffer * gst_disksrc_get (GstPad *pad);
|
||||
static GstBuffer * gst_disksrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len);
|
||||
static GstBuffer* gst_disksrc_get (GstPad *pad);
|
||||
static GstBufferPool* gst_disksrc_get_bufferpool (GstPad *pad);
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_disksrc_change_state (GstElement *element);
|
||||
|
@ -73,7 +73,7 @@ static GstElementStateReturn
|
|||
static gboolean gst_disksrc_open_file (GstDiskSrc *src);
|
||||
static void gst_disksrc_close_file (GstDiskSrc *src);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
static GstElementClass* parent_class = NULL;
|
||||
//static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
GType
|
||||
|
@ -133,8 +133,8 @@ gst_disksrc_init (GstDiskSrc *disksrc)
|
|||
// GST_FLAG_SET (disksrc, GST_SRC_);
|
||||
|
||||
disksrc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_pad_set_get_function (disksrc->srcpad,gst_disksrc_get);
|
||||
gst_pad_set_getregion_function (disksrc->srcpad,gst_disksrc_get_region);
|
||||
gst_pad_set_get_function (disksrc->srcpad, gst_disksrc_get);
|
||||
gst_pad_set_bufferpool_function (disksrc->srcpad, gst_disksrc_get_bufferpool);
|
||||
gst_element_add_pad (GST_ELEMENT (disksrc), disksrc->srcpad);
|
||||
|
||||
disksrc->filename = NULL;
|
||||
|
@ -220,6 +220,56 @@ gst_disksrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
}
|
||||
}
|
||||
|
||||
static GstBuffer*
|
||||
gst_disksrc_buffer_new (GstBufferPool *pool, gint64 location, gint size, gpointer user_data)
|
||||
{
|
||||
GstDiskSrc *src;
|
||||
GstBuffer *buf;
|
||||
|
||||
src = GST_DISKSRC (user_data);
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
/* simply set the buffer to point to the correct region of the file */
|
||||
GST_BUFFER_DATA (buf) = src->map + location;
|
||||
GST_BUFFER_OFFSET (buf) = location;
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
|
||||
|
||||
if ((location + size) > src->size)
|
||||
GST_BUFFER_SIZE (buf) = src->size - location;
|
||||
else
|
||||
GST_BUFFER_SIZE (buf) = size;
|
||||
|
||||
GST_DEBUG (0,"map %p, offset %ld (%p), size %d\n", src->map, src->curoffset,
|
||||
src->map + src->curoffset, GST_BUFFER_SIZE (buf));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_disksrc_buffer_free (GstBuffer *buf)
|
||||
{
|
||||
// FIXME do something here
|
||||
}
|
||||
|
||||
static GstBufferPool*
|
||||
gst_disksrc_get_bufferpool (GstPad *pad)
|
||||
{
|
||||
GstDiskSrc *src;
|
||||
|
||||
src = GST_DISKSRC (gst_pad_get_parent (pad));
|
||||
|
||||
if (!src->bufferpool) {
|
||||
src->bufferpool = gst_buffer_pool_new ();
|
||||
gst_buffer_pool_set_buffer_new_function (src->bufferpool, gst_disksrc_buffer_new);
|
||||
gst_buffer_pool_set_buffer_free_function (src->bufferpool, gst_disksrc_buffer_free);
|
||||
gst_buffer_pool_set_user_data (src->bufferpool, src);
|
||||
}
|
||||
|
||||
return src->bufferpool;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_disksrc_get:
|
||||
* @pad: #GstPad to push a buffer from
|
||||
|
@ -246,28 +296,10 @@ gst_disksrc_get (GstPad *pad)
|
|||
return buf;
|
||||
}
|
||||
|
||||
/* create the buffer */
|
||||
// FIXME: should eventually use a bufferpool for this
|
||||
buf = gst_buffer_new ();
|
||||
|
||||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
/* simply set the buffer to point to the correct region of the file */
|
||||
GST_BUFFER_DATA (buf) = src->map + src->curoffset;
|
||||
GST_BUFFER_OFFSET (buf) = src->curoffset;
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
|
||||
|
||||
if ((src->curoffset + src->bytes_per_read) > src->size) {
|
||||
GST_BUFFER_SIZE (buf) = src->size - src->curoffset;
|
||||
// FIXME: set the buffer's EOF bit here
|
||||
} else
|
||||
GST_BUFFER_SIZE (buf) = src->bytes_per_read;
|
||||
|
||||
GST_DEBUG (0,"map %p, offset %ld (%p), size %d\n", src->map, src->curoffset,
|
||||
src->map + src->curoffset, GST_BUFFER_SIZE (buf));
|
||||
// FIXME use a bufferpool
|
||||
buf = gst_disksrc_buffer_new (NULL, src->curoffset, src->bytes_per_read, src);
|
||||
|
||||
//gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
|
||||
src->curoffset += GST_BUFFER_SIZE (buf);
|
||||
|
||||
if (src->new_seek) {
|
||||
|
@ -280,61 +312,6 @@ gst_disksrc_get (GstPad *pad)
|
|||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_disksrc_get_region:
|
||||
* @src: #GstSrc to push a buffer from
|
||||
* @offset: offset in file
|
||||
* @size: number of bytes
|
||||
*
|
||||
* Push a new buffer from the disksrc of given size at given offset.
|
||||
*/
|
||||
static GstBuffer *
|
||||
gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
|
||||
{
|
||||
GstDiskSrc *src;
|
||||
GstBuffer *buf;
|
||||
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (type == GST_REGION_OFFSET_LEN, NULL);
|
||||
|
||||
src = GST_DISKSRC (gst_pad_get_parent (pad));
|
||||
|
||||
g_return_val_if_fail (GST_IS_DISKSRC (src), NULL);
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL);
|
||||
|
||||
/* deal with EOF state */
|
||||
if (offset >= src->size) {
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
GST_DEBUG (0,"map offset %lld >= size %ld --> eos\n", offset, src->size);
|
||||
//FIXME
|
||||
buf = gst_buffer_new();
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_EOS);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* create the buffer */
|
||||
// FIXME: should eventually use a bufferpool for this
|
||||
buf = gst_buffer_new ();
|
||||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
/* simply set the buffer to point to the correct region of the file */
|
||||
GST_BUFFER_DATA (buf) = src->map + offset;
|
||||
GST_BUFFER_OFFSET (buf) = offset;
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
|
||||
|
||||
if ((offset + len) > src->size) {
|
||||
GST_BUFFER_SIZE (buf) = src->size - offset;
|
||||
// FIXME: set the buffer's EOF bit here
|
||||
} else
|
||||
GST_BUFFER_SIZE (buf) = len;
|
||||
|
||||
GST_DEBUG (0,"map %p, offset %lld, size %d\n", src->map, offset, GST_BUFFER_SIZE (buf));
|
||||
|
||||
/* we're done, return the buffer off now */
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/* open the file and mmap it, necessary to go to READY state */
|
||||
static gboolean
|
||||
gst_disksrc_open_file (GstDiskSrc *src)
|
||||
|
|
|
@ -64,6 +64,7 @@ struct _GstDiskSrc {
|
|||
gchar *filename;
|
||||
/* fd */
|
||||
gint fd;
|
||||
GstBufferPool *bufferpool;
|
||||
|
||||
/* mapping parameters */
|
||||
gulong size; /* how long is the file? */
|
||||
|
|
|
@ -45,6 +45,7 @@ enum {
|
|||
ARG_0,
|
||||
ARG_NUM_SINKS,
|
||||
ARG_SILENT,
|
||||
ARG_DUMP,
|
||||
};
|
||||
|
||||
GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
|
||||
|
@ -58,7 +59,8 @@ GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
|
|||
static void gst_fakesink_class_init (GstFakeSinkClass *klass);
|
||||
static void gst_fakesink_init (GstFakeSink *fakesink);
|
||||
|
||||
static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ);
|
||||
static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const
|
||||
gchar *unused);
|
||||
|
||||
static void gst_fakesink_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
|
@ -66,7 +68,6 @@ static void gst_fakesink_get_property (GObject *object, guint prop_id,
|
|||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static void gst_fakesink_chain (GstPad *pad, GstBuffer *buf);
|
||||
static gboolean gst_fakesink_event (GstPad *pad, GstEventType event, guint64 timestamp, guint32 data);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
static guint gst_fakesink_signals[LAST_SIGNAL] = { 0 };
|
||||
|
@ -109,6 +110,9 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
|
|||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "silent", "silent",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_param_spec_boolean ("dump", "dump", "dump",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
gst_fakesink_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
|
@ -129,15 +133,15 @@ gst_fakesink_init (GstFakeSink *fakesink)
|
|||
pad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (fakesink), pad);
|
||||
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
|
||||
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_event));
|
||||
|
||||
fakesink->sinkpads = g_slist_prepend (NULL, pad);
|
||||
fakesink->numsinkpads = 1;
|
||||
fakesink->silent = FALSE;
|
||||
fakesink->dump = FALSE;
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
||||
gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *sinkpad;
|
||||
|
@ -175,6 +179,9 @@ gst_fakesink_set_property (GObject *object, guint prop_id, const GValue *value,
|
|||
case ARG_SILENT:
|
||||
sink->silent = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
sink->dump = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -197,6 +204,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
|||
case ARG_SILENT:
|
||||
g_value_set_boolean (value, sink->silent);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
g_value_set_boolean (value, sink->dump);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -206,9 +216,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
|||
/**
|
||||
* gst_fakesink_chain:
|
||||
* @pad: the pad this faksink is connected to
|
||||
* @buf: the buffer that has to be absorbed
|
||||
* @buffer: the buffer or event that has to be absorbed
|
||||
*
|
||||
* take the buffer from the pad and unref it without doing
|
||||
* Take the buffer or event from the pad and unref it without doing
|
||||
* anything with it.
|
||||
*/
|
||||
static void
|
||||
|
@ -221,12 +231,33 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
|
|||
g_return_if_fail (buf != NULL);
|
||||
|
||||
fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (GST_IS_EVENT(buf)) {
|
||||
GstEvent *event = GST_EVENT (buf);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
g_print("fakesink: have EOS event!\n");
|
||||
gst_element_set_state (GST_ELEMENT (fakesink), GST_STATE_PAUSED);
|
||||
break;
|
||||
default:
|
||||
g_print("fakesink: have unhandled event!\n");
|
||||
break;
|
||||
}
|
||||
gst_event_free (event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fakesink->silent)
|
||||
g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) \n",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
|
||||
g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0,
|
||||
buf);
|
||||
g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) %p\n",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
|
||||
|
||||
g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
|
||||
|
||||
if (fakesink->dump)
|
||||
{
|
||||
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
}
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
@ -238,14 +269,3 @@ gst_fakesink_factory_init (GstElementFactory *factory)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_fakesink_event (GstPad *pad, GstEventType event, guint64 timestamp, guint32 data)
|
||||
{
|
||||
GST_DEBUG (GST_CAT_EVENT, "fakesink has event %d on pad %s:%s\n",event,GST_DEBUG_PAD_NAME(pad));
|
||||
if (event == GST_EVENT_EOS) {
|
||||
GST_DEBUG(GST_CAT_EVENT, "have EOS\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ struct _GstFakeSink {
|
|||
GSList *sinkpads;
|
||||
gint numsinkpads;
|
||||
gboolean silent;
|
||||
gboolean dump;
|
||||
};
|
||||
|
||||
struct _GstFakeSinkClass {
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gstfakesrc.h>
|
||||
|
||||
|
||||
|
@ -47,10 +50,17 @@ enum {
|
|||
ARG_NUM_SOURCES,
|
||||
ARG_LOOP_BASED,
|
||||
ARG_OUTPUT,
|
||||
ARG_DATA,
|
||||
ARG_SIZETYPE,
|
||||
ARG_SIZEMIN,
|
||||
ARG_SIZEMAX,
|
||||
ARG_FILLTYPE,
|
||||
ARG_PATTERN,
|
||||
ARG_NUM_BUFFERS,
|
||||
ARG_EOS,
|
||||
ARG_SILENT
|
||||
ARG_SILENT,
|
||||
ARG_DUMP,
|
||||
ARG_PARENTSIZE
|
||||
};
|
||||
|
||||
GST_PADTEMPLATE_FACTORY (fakesrc_src_factory,
|
||||
|
@ -82,12 +92,69 @@ gst_fakesrc_output_get_type (void)
|
|||
return fakesrc_output_type;
|
||||
}
|
||||
|
||||
#define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type())
|
||||
static GType
|
||||
gst_fakesrc_data_get_type (void)
|
||||
{
|
||||
static GType fakesrc_data_type = 0;
|
||||
static GEnumValue fakesrc_data[] = {
|
||||
{ FAKESRC_DATA_ALLOCATE, "2", "Allocate data"},
|
||||
{ FAKESRC_DATA_SUBBUFFER, "3", "Subbuffer data"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_data_type) {
|
||||
fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data);
|
||||
}
|
||||
return fakesrc_data_type;
|
||||
}
|
||||
|
||||
#define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
|
||||
static GType
|
||||
gst_fakesrc_sizetype_get_type (void)
|
||||
{
|
||||
static GType fakesrc_sizetype_type = 0;
|
||||
static GEnumValue fakesrc_sizetype[] = {
|
||||
{ FAKESRC_SIZETYPE_NULL, "1", "Send empty buffers"},
|
||||
{ FAKESRC_SIZETYPE_FIXED, "2", "Fixed size buffers (sizemax sized)"},
|
||||
{ FAKESRC_SIZETYPE_RANDOM, "3", "Random sized buffers (sizemin <= size <= sizemax)"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_sizetype_type) {
|
||||
fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
|
||||
}
|
||||
return fakesrc_sizetype_type;
|
||||
}
|
||||
|
||||
#define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
|
||||
static GType
|
||||
gst_fakesrc_filltype_get_type (void)
|
||||
{
|
||||
static GType fakesrc_filltype_type = 0;
|
||||
static GEnumValue fakesrc_filltype[] = {
|
||||
{ FAKESRC_FILLTYPE_NOTHING, "1", "Leave data as malloced"},
|
||||
{ FAKESRC_FILLTYPE_NULL, "2", "Fill buffers with zeros"},
|
||||
{ FAKESRC_FILLTYPE_RANDOM, "3", "Fill buffers with random crap"},
|
||||
{ FAKESRC_FILLTYPE_PATTERN, "4", "Fill buffers with pattern 0x00 -> 0xff"},
|
||||
{ FAKESRC_FILLTYPE_PATTERN_CONT, "5", "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_filltype_type) {
|
||||
fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
|
||||
}
|
||||
return fakesrc_filltype_type;
|
||||
}
|
||||
|
||||
static void gst_fakesrc_class_init (GstFakeSrcClass *klass);
|
||||
static void gst_fakesrc_init (GstFakeSrc *fakesrc);
|
||||
|
||||
static GstPad* gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ);
|
||||
static void gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesrc_update_functions (GstFakeSrc *src);
|
||||
static void gst_fakesrc_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesrc_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static GstElementStateReturn gst_fakesrc_change_state (GstElement *element);
|
||||
|
||||
static GstBuffer* gst_fakesrc_get (GstPad *pad);
|
||||
static void gst_fakesrc_loop (GstElement *element);
|
||||
|
@ -137,6 +204,24 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
|
|||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT,
|
||||
g_param_spec_enum("output","output","output",
|
||||
GST_TYPE_FAKESRC_OUTPUT,FAKESRC_FIRST_LAST_LOOP,G_PARAM_READWRITE)); // CHECKME!
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
|
||||
g_param_spec_enum ("data", "data", "data",
|
||||
GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
|
||||
g_param_spec_enum ("sizetype", "sizetype", "sizetype",
|
||||
GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
|
||||
g_param_spec_int ("sizemin","sizemin","sizemin",
|
||||
0, G_MAXINT, 0, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
|
||||
g_param_spec_int ("sizemax","sizemax","sizemax",
|
||||
0, G_MAXINT, 4096, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
|
||||
g_param_spec_int ("parentsize","parentsize","parentsize",
|
||||
0, G_MAXINT, 4096 * 10, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
|
||||
g_param_spec_enum ("filltype", "filltype", "filltype",
|
||||
GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PATTERN,
|
||||
g_param_spec_string("pattern","pattern","pattern",
|
||||
NULL, G_PARAM_READWRITE)); // CHECKME
|
||||
|
@ -149,6 +234,9 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
|
|||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SILENT,
|
||||
g_param_spec_boolean("silent","silent","silent",
|
||||
FALSE, G_PARAM_READWRITE)); // CHECKME
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_param_spec_boolean ("dump","dump","dump",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
gst_fakesrc_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
|
@ -159,7 +247,8 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
|
|||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -176,17 +265,21 @@ gst_fakesrc_init (GstFakeSrc *fakesrc)
|
|||
fakesrc->srcpads = g_slist_append (NULL, pad);
|
||||
|
||||
fakesrc->loop_based = FALSE;
|
||||
|
||||
if (fakesrc->loop_based)
|
||||
gst_element_set_loop_function (GST_ELEMENT (fakesrc), GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
|
||||
else
|
||||
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
|
||||
gst_fakesrc_update_functions (fakesrc);
|
||||
|
||||
fakesrc->num_buffers = -1;
|
||||
fakesrc->buffer_count = 0;
|
||||
fakesrc->silent = FALSE;
|
||||
// we're ready right away, since we don't have any args...
|
||||
// gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_READY);
|
||||
fakesrc->dump = FALSE;
|
||||
fakesrc->pattern_byte = 0x00;
|
||||
fakesrc->need_flush = FALSE;
|
||||
fakesrc->data = FAKESRC_DATA_ALLOCATE;
|
||||
fakesrc->sizetype = FAKESRC_SIZETYPE_NULL;
|
||||
fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING;
|
||||
fakesrc->sizemin = 0;
|
||||
fakesrc->sizemax = 4096;
|
||||
fakesrc->parent = NULL;
|
||||
fakesrc->parentsize = 4096 * 10;
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
|
@ -216,6 +309,34 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
|||
return srcpad;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
GstFakeSrc *src;
|
||||
|
||||
src = GST_FAKESRC (gst_pad_get_parent (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
g_print("fakesrc: have seek event\n");
|
||||
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
||||
if (!GST_EVENT_SEEK_FLUSH (event)) {
|
||||
gst_event_free (event);
|
||||
break;
|
||||
}
|
||||
// else we do a flush too
|
||||
case GST_EVENT_FLUSH:
|
||||
g_print("fakesrc: have flush event\n");
|
||||
src->need_flush = TRUE;
|
||||
break;
|
||||
default:
|
||||
g_print("fakesrc: have unhandled event\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_update_functions (GstFakeSrc *src)
|
||||
{
|
||||
|
@ -238,10 +359,25 @@ gst_fakesrc_update_functions (GstFakeSrc *src)
|
|||
else {
|
||||
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
|
||||
}
|
||||
|
||||
gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
|
||||
pads = g_slist_next (pads);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_alloc_parent (GstFakeSrc *src)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
|
||||
GST_BUFFER_SIZE (buf) = src->parentsize;
|
||||
|
||||
src->parent = buf;
|
||||
src->parentoffset = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
|
@ -257,6 +393,37 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
break;
|
||||
case ARG_OUTPUT:
|
||||
break;
|
||||
case ARG_DATA:
|
||||
src->data = g_value_get_int (value);
|
||||
switch (src->data) {
|
||||
case FAKESRC_DATA_ALLOCATE:
|
||||
if (src->parent) {
|
||||
gst_buffer_unref (src->parent);
|
||||
src->parent = NULL;
|
||||
}
|
||||
break;
|
||||
case FAKESRC_DATA_SUBBUFFER:
|
||||
if (!src->parent)
|
||||
gst_fakesrc_alloc_parent (src);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ARG_SIZETYPE:
|
||||
src->sizetype = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_SIZEMIN:
|
||||
src->sizemin = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_SIZEMAX:
|
||||
src->sizemax = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_PARENTSIZE:
|
||||
src->parentsize = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_FILLTYPE:
|
||||
src->filltype = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_PATTERN:
|
||||
break;
|
||||
case ARG_NUM_BUFFERS:
|
||||
|
@ -269,6 +436,9 @@ GST_INFO (0, "will EOS on next buffer");
|
|||
case ARG_SILENT:
|
||||
src->silent = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
src->dump = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -294,6 +464,24 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
case ARG_OUTPUT:
|
||||
g_value_set_int (value, src->output);
|
||||
break;
|
||||
case ARG_DATA:
|
||||
g_value_set_int (value, src->data);
|
||||
break;
|
||||
case ARG_SIZETYPE:
|
||||
g_value_set_int (value, src->sizetype);
|
||||
break;
|
||||
case ARG_SIZEMIN:
|
||||
g_value_set_int (value, src->sizemin);
|
||||
break;
|
||||
case ARG_SIZEMAX:
|
||||
g_value_set_int (value, src->sizemax);
|
||||
break;
|
||||
case ARG_PARENTSIZE:
|
||||
g_value_set_int (value, src->parentsize);
|
||||
break;
|
||||
case ARG_FILLTYPE:
|
||||
g_value_set_int (value, src->filltype);
|
||||
break;
|
||||
case ARG_PATTERN:
|
||||
g_value_set_string (value, src->pattern);
|
||||
break;
|
||||
|
@ -306,21 +494,150 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
case ARG_SILENT:
|
||||
g_value_set_boolean (value, src->silent);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
g_value_set_boolean (value, src->dump);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
|
||||
{
|
||||
if (GST_BUFFER_SIZE (buf) == 0)
|
||||
return;
|
||||
|
||||
switch (src->filltype) {
|
||||
case FAKESRC_FILLTYPE_NULL:
|
||||
memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
|
||||
break;
|
||||
case FAKESRC_FILLTYPE_RANDOM:
|
||||
{
|
||||
gint i;
|
||||
guint8 *ptr = GST_BUFFER_DATA (buf);
|
||||
|
||||
for (i = GST_BUFFER_SIZE (buf); i; i--) {
|
||||
*ptr++ = (gint8)((255.0)*rand()/(RAND_MAX));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FAKESRC_FILLTYPE_PATTERN:
|
||||
src->pattern_byte = 0x00;
|
||||
case FAKESRC_FILLTYPE_PATTERN_CONT:
|
||||
{
|
||||
gint i;
|
||||
guint8 *ptr = GST_BUFFER_DATA (buf);
|
||||
|
||||
for (i = GST_BUFFER_SIZE (buf); i; i--) {
|
||||
*ptr++ = src->pattern_byte++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FAKESRC_FILLTYPE_NOTHING:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GstBuffer*
|
||||
gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_SIZE(buf) = size;
|
||||
|
||||
if (size != 0) {
|
||||
switch (src->filltype) {
|
||||
case FAKESRC_FILLTYPE_NOTHING:
|
||||
GST_BUFFER_DATA(buf) = g_malloc (size);
|
||||
break;
|
||||
case FAKESRC_FILLTYPE_NULL:
|
||||
GST_BUFFER_DATA(buf) = g_malloc0 (size);
|
||||
break;
|
||||
case FAKESRC_FILLTYPE_RANDOM:
|
||||
case FAKESRC_FILLTYPE_PATTERN:
|
||||
case FAKESRC_FILLTYPE_PATTERN_CONT:
|
||||
default:
|
||||
GST_BUFFER_DATA(buf) = g_malloc (size);
|
||||
gst_fakesrc_prepare_buffer (src, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static guint
|
||||
gst_fakesrc_get_size (GstFakeSrc *src)
|
||||
{
|
||||
guint size;
|
||||
|
||||
switch (src->sizetype) {
|
||||
case FAKESRC_SIZETYPE_FIXED:
|
||||
size = src->sizemax;
|
||||
break;
|
||||
case FAKESRC_SIZETYPE_RANDOM:
|
||||
size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin));
|
||||
break;
|
||||
case FAKESRC_SIZETYPE_NULL:
|
||||
default:
|
||||
size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_fakesrc_create_buffer (GstFakeSrc *src)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
guint size;
|
||||
gboolean dump = src->dump;
|
||||
|
||||
size = gst_fakesrc_get_size (src);
|
||||
if (size == 0)
|
||||
return gst_buffer_new();
|
||||
|
||||
switch (src->data) {
|
||||
case FAKESRC_DATA_ALLOCATE:
|
||||
buf = gst_fakesrc_alloc_buffer (src, size);
|
||||
break;
|
||||
case FAKESRC_DATA_SUBBUFFER:
|
||||
// see if we have a parent to subbuffer
|
||||
if (!src->parent) {
|
||||
gst_fakesrc_alloc_parent (src);
|
||||
g_assert (src->parent);
|
||||
}
|
||||
// see if it's large enough
|
||||
if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
|
||||
buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
|
||||
src->parentoffset += size;
|
||||
}
|
||||
else {
|
||||
// the parent is useless now
|
||||
gst_buffer_unref (src->parent);
|
||||
src->parent = NULL;
|
||||
// try again (this will allocate a new parent)
|
||||
return gst_fakesrc_create_buffer (src);
|
||||
}
|
||||
gst_fakesrc_prepare_buffer (src, buf);
|
||||
break;
|
||||
default:
|
||||
g_warning ("fakesrc: dunno how to allocate buffers !");
|
||||
buf = gst_buffer_new();
|
||||
break;
|
||||
}
|
||||
if (dump) {
|
||||
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_fakesrc_get:
|
||||
* @src: the faksesrc to get
|
||||
*
|
||||
* generate an empty buffer and return it
|
||||
*
|
||||
* Returns: a new empty buffer
|
||||
*/
|
||||
static GstBuffer *
|
||||
gst_fakesrc_get(GstPad *pad)
|
||||
{
|
||||
|
@ -333,9 +650,16 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
g_return_val_if_fail (GST_IS_FAKESRC (src), NULL);
|
||||
|
||||
if (src->need_flush) {
|
||||
src->need_flush = FALSE;
|
||||
g_print("fakesrc: sending FLUSH\n");
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
|
||||
}
|
||||
|
||||
if (src->num_buffers == 0) {
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
return NULL;
|
||||
g_print("fakesrc: sending EOS\n");
|
||||
gst_element_set_state (GST_ELEMENT (src), GST_STATE_PAUSED);
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
else {
|
||||
if (src->num_buffers > 0)
|
||||
|
@ -344,11 +668,11 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
if (src->eos) {
|
||||
GST_INFO (0, "fakesrc is setting eos on pad");
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
return NULL;
|
||||
g_print("fakesrc: sending EOS\n");
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
||||
buf = gst_buffer_new();
|
||||
buf = gst_fakesrc_create_buffer (src);
|
||||
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
|
||||
|
||||
if (!src->silent)
|
||||
|
@ -356,7 +680,7 @@ gst_fakesrc_get(GstPad *pad)
|
|||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
buf);
|
||||
buf, pad);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -387,21 +711,20 @@ gst_fakesrc_loop(GstElement *element)
|
|||
GstBuffer *buf;
|
||||
|
||||
if (src->num_buffers == 0) {
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
return;
|
||||
src->eos = TRUE;
|
||||
}
|
||||
else {
|
||||
if (src->num_buffers > 0)
|
||||
src->num_buffers--;
|
||||
if (src->num_buffers > 0)
|
||||
src->num_buffers--;
|
||||
}
|
||||
|
||||
if (src->eos) {
|
||||
GST_INFO (0, "fakesrc is setting eos on pad");
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
return;
|
||||
gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
|
||||
return;
|
||||
}
|
||||
|
||||
buf = gst_buffer_new();
|
||||
buf = gst_fakesrc_create_buffer (src);
|
||||
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
|
||||
|
||||
if (!src->silent)
|
||||
|
@ -409,7 +732,7 @@ gst_fakesrc_loop(GstElement *element)
|
|||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
buf);
|
||||
buf, pad);
|
||||
gst_pad_push (pad, buf);
|
||||
|
||||
pads = g_slist_next (pads);
|
||||
|
@ -417,6 +740,31 @@ gst_fakesrc_loop(GstElement *element)
|
|||
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_fakesrc_change_state (GstElement *element)
|
||||
{
|
||||
GstFakeSrc *fakesrc;
|
||||
|
||||
g_return_val_if_fail (GST_IS_FAKESRC (element), GST_STATE_FAILURE);
|
||||
|
||||
fakesrc = GST_FAKESRC (element);
|
||||
|
||||
if (GST_STATE_PENDING (element) == GST_STATE_READY) {
|
||||
fakesrc->buffer_count = 0;
|
||||
fakesrc->pattern_byte = 0x00;
|
||||
fakesrc->need_flush = FALSE;
|
||||
if (fakesrc->parent) {
|
||||
gst_buffer_unref (fakesrc->parent);
|
||||
fakesrc->parent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_fakesrc_factory_init (GstElementFactory *factory)
|
||||
{
|
||||
|
|
|
@ -47,6 +47,25 @@ typedef enum {
|
|||
FAKESRC_GET_ALWAYS_SUCEEDS,
|
||||
} GstFakeSrcOutputType;
|
||||
|
||||
typedef enum {
|
||||
FAKESRC_DATA_ALLOCATE = 1,
|
||||
FAKESRC_DATA_SUBBUFFER,
|
||||
} GstFakeSrcDataType;
|
||||
|
||||
typedef enum {
|
||||
FAKESRC_SIZETYPE_NULL = 1,
|
||||
FAKESRC_SIZETYPE_FIXED,
|
||||
FAKESRC_SIZETYPE_RANDOM
|
||||
} GstFakeSrcSizeType;
|
||||
|
||||
typedef enum {
|
||||
FAKESRC_FILLTYPE_NOTHING = 1,
|
||||
FAKESRC_FILLTYPE_NULL,
|
||||
FAKESRC_FILLTYPE_RANDOM,
|
||||
FAKESRC_FILLTYPE_PATTERN,
|
||||
FAKESRC_FILLTYPE_PATTERN_CONT
|
||||
} GstFakeSrcFillType;
|
||||
|
||||
#define GST_TYPE_FAKESRC \
|
||||
(gst_fakesrc_get_type())
|
||||
#define GST_FAKESRC(obj) \
|
||||
|
@ -64,16 +83,29 @@ typedef struct _GstFakeSrcClass GstFakeSrcClass;
|
|||
struct _GstFakeSrc {
|
||||
GstElement element;
|
||||
|
||||
gboolean loop_based;
|
||||
gboolean eos;
|
||||
gint numsrcpads;
|
||||
GSList *srcpads;
|
||||
gboolean loop_based;
|
||||
gboolean eos;
|
||||
gint numsrcpads;
|
||||
GSList *srcpads;
|
||||
|
||||
GstFakeSrcOutputType output;
|
||||
gchar *pattern;
|
||||
GList *patternlist;
|
||||
gint num_buffers;
|
||||
guint64 buffer_count;
|
||||
gboolean silent;
|
||||
GstFakeSrcDataType data;
|
||||
GstFakeSrcSizeType sizetype;
|
||||
GstFakeSrcFillType filltype;
|
||||
|
||||
guint sizemin;
|
||||
guint sizemax;
|
||||
GstBuffer *parent;
|
||||
guint parentsize;
|
||||
guint parentoffset;
|
||||
guint8 pattern_byte;
|
||||
gchar *pattern;
|
||||
GList *patternlist;
|
||||
gint num_buffers;
|
||||
guint64 buffer_count;
|
||||
gboolean silent;
|
||||
gboolean dump;
|
||||
gboolean need_flush;
|
||||
};
|
||||
|
||||
struct _GstFakeSrcClass {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -74,6 +75,9 @@ GstElementDetails gst_filesrc_details = {
|
|||
"(C) 1999",
|
||||
};
|
||||
|
||||
//#define fs_print(format,args...) g_print(format, ## args)
|
||||
#define fs_print(format,args...)
|
||||
|
||||
|
||||
#define GST_TYPE_FILESRC \
|
||||
(gst_filesrc_get_type())
|
||||
|
@ -110,10 +114,12 @@ struct _GstFileSrc {
|
|||
gboolean touch; // whether to touch every page
|
||||
|
||||
GstBuffer *mapbuf;
|
||||
off_t mapsize;
|
||||
size_t mapsize;
|
||||
|
||||
GTree *map_regions;
|
||||
GMutex *map_regions_lock;
|
||||
|
||||
gboolean seek_happened;
|
||||
};
|
||||
|
||||
struct _GstFileSrcClass {
|
||||
|
@ -135,6 +141,7 @@ enum {
|
|||
ARG_BLOCKSIZE,
|
||||
ARG_OFFSET,
|
||||
ARG_MAPSIZE,
|
||||
ARG_TOUCH,
|
||||
};
|
||||
|
||||
|
||||
|
@ -203,6 +210,9 @@ gst_filesrc_class_init (GstFileSrcClass *klass)
|
|||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MAPSIZE,
|
||||
g_param_spec_ulong("mmapsize","mmap() Block Size","Size in bytes of mmap()d regions",
|
||||
0,G_MAXULONG,4*1048576,G_PARAM_READWRITE));
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TOUCH,
|
||||
g_param_spec_boolean("touch","Touch read data","Touch data to force disk read before push()",
|
||||
TRUE,G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->set_property = gst_filesrc_set_property;
|
||||
gobject_class->get_property = gst_filesrc_get_property;
|
||||
|
@ -246,6 +256,8 @@ gst_filesrc_init (GstFileSrc *src)
|
|||
|
||||
src->map_regions = g_tree_new(gst_filesrc_bufcmp);
|
||||
src->map_regions_lock = g_mutex_new();
|
||||
|
||||
src->seek_happened = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -286,6 +298,9 @@ gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
else
|
||||
GST_INFO(0, "invalid mapsize, must a multiple of pagesize, which is %d\n",src->pagesize);
|
||||
break;
|
||||
case ARG_TOUCH:
|
||||
src->touch = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -320,6 +335,9 @@ gst_filesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
case ARG_MAPSIZE:
|
||||
g_value_set_ulong (value, src->mapsize);
|
||||
break;
|
||||
case ARG_TOUCH:
|
||||
g_value_set_boolean (value, src->touch);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -331,7 +349,7 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
|
|||
{
|
||||
GstFileSrc *src = GST_FILESRC(GST_BUFFER_POOL_PRIVATE(buf));
|
||||
|
||||
// fprintf(stderr,"freeing mmap()d buffer at %d+%d\n",GST_BUFFER_OFFSET(buf),GST_BUFFER_SIZE(buf));
|
||||
fs_print ("freeing mmap()d buffer at %d+%d\n",GST_BUFFER_OFFSET(buf),GST_BUFFER_SIZE(buf));
|
||||
|
||||
// remove the buffer from the list of available mmap'd regions
|
||||
g_mutex_lock(src->map_regions_lock);
|
||||
|
@ -347,21 +365,24 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
|
|||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_filesrc_map_region (GstFileSrc *src, off_t offset, off_t size)
|
||||
gst_filesrc_map_region (GstFileSrc *src, off_t offset, size_t size)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
gint retval;
|
||||
|
||||
// fprintf(stderr,"mapping region %d+%d from file into memory\n",offset,size);
|
||||
g_return_val_if_fail (offset >= 0, NULL);
|
||||
|
||||
fs_print ("mapping region %08lx+%08lx from file into memory\n",offset,size);
|
||||
|
||||
// time to allocate a new mapbuf
|
||||
buf = gst_buffer_new();
|
||||
// mmap() the data into this new buffer
|
||||
GST_BUFFER_DATA(buf) = mmap (NULL, size, PROT_READ, MAP_SHARED, src->fd, offset);
|
||||
if (GST_BUFFER_DATA(buf) == NULL) {
|
||||
fprintf(stderr, "ERROR: gstfilesrc couldn't map file!\n");
|
||||
} else if (GST_BUFFER_DATA(buf) == (void *)-1) {
|
||||
perror("gstfilesrc:mmap()");
|
||||
fprintf (stderr, "ERROR: gstfilesrc couldn't map file!\n");
|
||||
} else if (GST_BUFFER_DATA(buf) == MAP_FAILED) {
|
||||
g_error ("gstfilesrc mmap(0x%x, %d, 0x%llx) : %s",
|
||||
size, src->fd, offset, sys_errlist[errno]);
|
||||
}
|
||||
// madvise to tell the kernel what to do with it
|
||||
retval = madvise(GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf),MADV_SEQUENTIAL);
|
||||
|
@ -382,20 +403,27 @@ gst_filesrc_map_region (GstFileSrc *src, off_t offset, off_t size)
|
|||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, off_t size)
|
||||
gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, size_t size)
|
||||
{
|
||||
int mod, mapbase, mapsize;
|
||||
size_t mapsize;
|
||||
off_t mod, mapbase;
|
||||
GstBuffer *map;
|
||||
|
||||
// printf("attempting to map a small buffer at %d+%d\n",offset,size);
|
||||
|
||||
// if the offset starts at a non-page boundary, we have to special case
|
||||
if ((mod = offset % src->pagesize)) {
|
||||
GstBuffer *ret;
|
||||
|
||||
mapbase = offset - mod;
|
||||
mapsize = ((size + mod + src->pagesize - 1) / src->pagesize) * src->pagesize;
|
||||
// printf("not on page boundaries, resizing map to %d+%d\n",mapbase,mapsize);
|
||||
map = gst_filesrc_map_region(src, mapbase, mapsize);
|
||||
return gst_buffer_create_sub (map, offset - mapbase, size);
|
||||
ret = gst_buffer_create_sub (map, offset - mapbase, size);
|
||||
|
||||
gst_buffer_unref (map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return gst_filesrc_map_region(src,offset,size);
|
||||
|
@ -431,8 +459,8 @@ gst_filesrc_get (GstPad *pad)
|
|||
{
|
||||
GstFileSrc *src;
|
||||
GstBuffer *buf = NULL, *map;
|
||||
off_t readend,readsize,mapstart,mapend;
|
||||
gboolean eof = FALSE;
|
||||
size_t readsize;
|
||||
off_t readend,mapstart,mapend;
|
||||
GstFileSrcRegion region;
|
||||
int i;
|
||||
|
||||
|
@ -440,6 +468,18 @@ gst_filesrc_get (GstPad *pad)
|
|||
src = GST_FILESRC (gst_pad_get_parent (pad));
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN), NULL);
|
||||
|
||||
// check for seek
|
||||
if (src->seek_happened) {
|
||||
src->seek_happened = FALSE;
|
||||
return gst_event_new(GST_EVENT_DISCONTINUOUS);
|
||||
}
|
||||
|
||||
// check for EOF
|
||||
if (src->curoffset == src->filelen) {
|
||||
gst_element_set_state(src,GST_STATE_PAUSED);
|
||||
return gst_event_new(GST_EVENT_EOS);
|
||||
}
|
||||
|
||||
// calculate end pointers so we don't have to do so repeatedly later
|
||||
readsize = src->block_size;
|
||||
readend = src->curoffset + src->block_size; // note this is the byte *after* the read
|
||||
|
@ -450,7 +490,6 @@ gst_filesrc_get (GstPad *pad)
|
|||
if (readend > src->filelen) {
|
||||
readsize = src->filelen - src->curoffset;
|
||||
readend = src->curoffset;
|
||||
eof = TRUE;
|
||||
}
|
||||
|
||||
// if the start is past the mapstart
|
||||
|
@ -458,15 +497,15 @@ gst_filesrc_get (GstPad *pad)
|
|||
// if the end is before the mapend, the buffer is in current mmap region...
|
||||
// ('cause by definition if readend is in the buffer, so's readstart)
|
||||
if (readend <= mapend) {
|
||||
// printf("read buf %d+%d lives in current mapbuf %d+%d, creating subbuffer of mapbuf\n",
|
||||
// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
fs_print ("read buf %d+%d lives in current mapbuf %d+%d, creating subbuffer of mapbuf\n",
|
||||
src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
buf = gst_buffer_create_sub (src->mapbuf, src->curoffset - GST_BUFFER_OFFSET(src->mapbuf),
|
||||
readsize);
|
||||
|
||||
// if the start actually is within the current mmap region, map an overlap buffer
|
||||
} else if (src->curoffset < mapend) {
|
||||
// printf("read buf %d+%d starts in mapbuf %d+%d but ends outside, creating new mmap\n",
|
||||
// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
fs_print ("read buf %d+%d starts in mapbuf %d+%d but ends outside, creating new mmap\n",
|
||||
src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
}
|
||||
|
||||
|
@ -478,37 +517,39 @@ gst_filesrc_get (GstPad *pad)
|
|||
// either the read buffer overlaps the start of the mmap region
|
||||
// or the read buffer fully contains the current mmap region
|
||||
// either way, it's really not relevant, we just create a new region anyway
|
||||
// printf("read buf %d+%d starts before mapbuf %d+%d, but overlaps it\n",
|
||||
// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
fs_print ("read buf %d+%d starts before mapbuf %d+%d, but overlaps it\n",
|
||||
src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
}
|
||||
|
||||
// then deal with the case where the read buffer is totally outside
|
||||
if (buf == NULL) {
|
||||
// first check to see if there's a map that covers the right region already
|
||||
// printf("searching for mapbuf to cover %d+%d\n",src->curoffset,readsize);
|
||||
fs_print ("searching for mapbuf to cover %d+%d\n",src->curoffset,readsize);
|
||||
region.offset = src->curoffset;
|
||||
region.size = readsize;
|
||||
map = g_tree_search(src->map_regions,gst_filesrc_search_region_match,®ion);
|
||||
map = g_tree_search (src->map_regions,
|
||||
(GCompareFunc) gst_filesrc_search_region_match,
|
||||
®ion);
|
||||
|
||||
// if we found an exact match, subbuffer it
|
||||
if (map != NULL) {
|
||||
// printf("found mapbuf at %d+%d, creating subbuffer\n",GST_BUFFER_OFFSET(map),GST_BUFFER_SIZE(map));
|
||||
fs_print ("found mapbuf at %d+%d, creating subbuffer\n",GST_BUFFER_OFFSET(map),GST_BUFFER_SIZE(map));
|
||||
buf = gst_buffer_create_sub (map, src->curoffset - GST_BUFFER_OFFSET(map), readsize);
|
||||
|
||||
// otherwise we need to create something out of thin air
|
||||
} else {
|
||||
// if the read buffer crosses a mmap region boundary, create a one-off region
|
||||
if ((src->curoffset / src->mapsize) != (readend / src->mapsize)) {
|
||||
// printf("read buf %d+%d crosses a %d-byte boundary, creating a one-off\n",
|
||||
// src->curoffset,readsize,src->mapsize);
|
||||
fs_print ("read buf %d+%d crosses a %d-byte boundary, creating a one-off\n",
|
||||
src->curoffset,readsize,src->mapsize);
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
|
||||
// otherwise we will create a new mmap region and set it to the default
|
||||
} else {
|
||||
off_t nextmap = src->curoffset - (src->curoffset % src->mapsize);
|
||||
// printf("read buf %d+%d in new mapbuf at %d+%d, mapping and subbuffering\n",
|
||||
// src->curoffset,readsize,nextmap,src->mapsize);
|
||||
fs_print ("read buf %d+%d in new mapbuf at %d+%d, mapping and subbuffering\n",
|
||||
src->curoffset,readsize,nextmap,src->mapsize);
|
||||
// first, we're done with the old mapbuf
|
||||
gst_buffer_unref(src->mapbuf);
|
||||
// create a new one
|
||||
|
@ -525,8 +566,6 @@ gst_filesrc_get (GstPad *pad)
|
|||
*(GST_BUFFER_DATA(buf)+i) = *(GST_BUFFER_DATA(buf)+i);
|
||||
}
|
||||
|
||||
// if we hit EOF,
|
||||
|
||||
/* we're done, return the buffer */
|
||||
src->curoffset += GST_BUFFER_SIZE(buf);
|
||||
return buf;
|
||||
|
@ -567,6 +606,7 @@ gst_filesrc_close_file (GstFileSrc *src)
|
|||
{
|
||||
g_return_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN));
|
||||
|
||||
g_print ("close\n");
|
||||
/* close the file */
|
||||
close (src->fd);
|
||||
|
||||
|
@ -613,6 +653,7 @@ gst_filesrc_srcpad_event(GstPad *pad, GstEventType event, gint64 location, guint
|
|||
} else if (data == SEEK_END) {
|
||||
src->curoffset = src->filelen - (guint64)location;
|
||||
}
|
||||
src->seek_happened = TRUE;
|
||||
// push a discontinuous event?
|
||||
return TRUE;
|
||||
}
|
||||
|
|
452
gst/elements/gstsinesrc.c
Normal file
452
gst/elements/gstsinesrc.c
Normal file
|
@ -0,0 +1,452 @@
|
|||
/* 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;
|
||||
}
|
96
gst/elements/gstsinesrc.h
Normal file
96
gst/elements/gstsinesrc.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* 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__ */
|
|
@ -56,7 +56,7 @@ GST_PADTEMPLATE_FACTORY (tee_src_factory,
|
|||
static void gst_tee_class_init (GstTeeClass *klass);
|
||||
static void gst_tee_init (GstTee *tee);
|
||||
|
||||
static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp);
|
||||
static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp, const gchar *unused);
|
||||
|
||||
static void gst_tee_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
|
@ -127,7 +127,7 @@ gst_tee_init (GstTee *tee)
|
|||
}
|
||||
|
||||
static GstPad*
|
||||
gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
||||
gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *srcpad;
|
||||
|
|
|
@ -6,6 +6,24 @@
|
|||
#include "gobject2gtk.h"
|
||||
|
||||
|
||||
// list functions not in glib 1.2
|
||||
GList *
|
||||
g_list_delete_link (GList *list, GList *llink)
|
||||
{
|
||||
GList *temp = g_list_remove_link(list, llink);
|
||||
g_list_free(llink);
|
||||
return temp;
|
||||
}
|
||||
|
||||
GSList *
|
||||
g_slist_delete_link (GSList *list, GSList *llink)
|
||||
{
|
||||
GSList *temp = g_slist_remove_link(list, llink);
|
||||
g_slist_free(llink);
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// GObject dummy implementation
|
||||
static void
|
||||
|
@ -324,4 +342,3 @@ gint* g_signal_list_ids (GType type, guint *n_ids)
|
|||
|
||||
return class->signals;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
#define G_PI_4 0.78539816339744830962E0
|
||||
#define G_SQRT2 1.4142135623730950488E0
|
||||
|
||||
// lists functions not in glib 1.2
|
||||
GList *g_list_delete_link (GList *list, GList *llink);
|
||||
GSList *g_slist_delete_link (GSList *list, GSList *llink);
|
||||
|
||||
|
||||
// GObject
|
||||
typedef struct _GObject GObject;
|
||||
typedef struct _GObjectClass GObjectClass;
|
||||
|
||||
|
@ -53,35 +59,35 @@ typedef struct _GObjectClass GObjectClass;
|
|||
#define G_TYPE_PARAM GTK_TYPE_PARAM
|
||||
|
||||
// marshallers
|
||||
#define g_cclosure_marshal_VOID__VOID gtk_marshal_NONE__NONE
|
||||
#define g_cclosure_marshal_VOID__BOOLEAN gtk_marshal_NONE__BOOL
|
||||
#define g_cclosure_marshal_VOID__CHAR gtk_marshal_NONE__CHAR
|
||||
#define g_cclosure_marshal_VOID__UCHAR gtk_marshal_NONE__UCHAR
|
||||
#define g_cclosure_marshal_VOID__INT gtk_marshal_NONE__INT
|
||||
#define g_cclosure_marshal_VOID__UINT gtk_marshal_NONE__UINT
|
||||
#define g_cclosure_marshal_VOID__LONG gtk_marshal_NONE__LONG
|
||||
#define g_cclosure_marshal_VOID__ULONG gtk_marshal_NONE__ULONG
|
||||
#define g_cclosure_marshal_VOID__ENUM gtk_marshal_NONE__ENUM
|
||||
#define g_cclosure_marshal_VOID__FLAGS gtk_marshal_NONE__FLAGS
|
||||
#define g_cclosure_marshal_VOID__FLOAT gtk_marshal_NONE__FLOAT
|
||||
#define g_cclosure_marshal_VOID__DOUBLE gtk_marshal_NONE__DOUBLE
|
||||
#define g_cclosure_marshal_VOID__STRING gtk_marshal_NONE__STRING
|
||||
#define g_cclosure_marshal_VOID__PARAM gtk_marshal_NONE__PARAM
|
||||
#define g_cclosure_marshal_VOID__BOXED gtk_marshal_NONE__BOXED
|
||||
#define g_cclosure_marshal_VOID__POINTER gtk_marshal_NONE__POINTER
|
||||
#define g_cclosure_marshal_VOID__OBJECT gtk_marshal_NONE__OBJECT
|
||||
#define g_cclosure_marshal_STRING__OBJECT_POINTER gtk_marshal_STRING__OBJECT_POINTER
|
||||
#define g_cclosure_marshal_VOID__UINT_POINTER gtk_marshal_NONE__UINT_POINTER
|
||||
#define g_cclosure_marshal_VOID__VOID gtk_marshal_NONE__NONE
|
||||
#define g_cclosure_marshal_VOID__BOOLEAN gtk_marshal_NONE__BOOL
|
||||
#define g_cclosure_marshal_VOID__CHAR gtk_marshal_NONE__CHAR
|
||||
#define g_cclosure_marshal_VOID__UCHAR gtk_marshal_NONE__UCHAR
|
||||
#define g_cclosure_marshal_VOID__INT gtk_marshal_NONE__INT
|
||||
#define g_cclosure_marshal_VOID__UINT gtk_marshal_NONE__UINT
|
||||
#define g_cclosure_marshal_VOID__LONG gtk_marshal_NONE__LONG
|
||||
#define g_cclosure_marshal_VOID__ULONG gtk_marshal_NONE__ULONG
|
||||
#define g_cclosure_marshal_VOID__ENUM gtk_marshal_NONE__ENUM
|
||||
#define g_cclosure_marshal_VOID__FLAGS gtk_marshal_NONE__FLAGS
|
||||
#define g_cclosure_marshal_VOID__FLOAT gtk_marshal_NONE__FLOAT
|
||||
#define g_cclosure_marshal_VOID__DOUBLE gtk_marshal_NONE__DOUBLE
|
||||
#define g_cclosure_marshal_VOID__STRING gtk_marshal_NONE__STRING
|
||||
#define g_cclosure_marshal_VOID__PARAM gtk_marshal_NONE__PARAM
|
||||
#define g_cclosure_marshal_VOID__BOXED gtk_marshal_NONE__BOXED
|
||||
#define g_cclosure_marshal_VOID__POINTER gtk_marshal_NONE__POINTER
|
||||
#define g_cclosure_marshal_VOID__OBJECT gtk_marshal_NONE__OBJECT
|
||||
#define g_cclosure_marshal_STRING__OBJECT_POINTER gtk_marshal_STRING__POINTER_POINTER
|
||||
#define g_cclosure_marshal_VOID__UINT_POINTER gtk_marshal_NONE__UINT_POINTER
|
||||
|
||||
#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT
|
||||
#define gst_marshal_VOID__INT gtk_marshal_NONE__INT
|
||||
#define gst_marshal_VOID__STRING gtk_marshal_NONE__STRING
|
||||
#define gst_marshal_VOID__VOID gtk_marshal_NONE__NONE
|
||||
#define gst_marshal_VOID__BOOLEAN gtk_marshal_NONE__BOOL
|
||||
#define gst_marshal_VOID__INT gtk_marshal_NONE__INT
|
||||
#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT
|
||||
#define gst_marshal_VOID__STRING gtk_marshal_NONE__STRING
|
||||
#define gst_marshal_VOID__POINTER gtk_marshal_NONE__POINTER
|
||||
#define gst_marshal_VOID__OBJECT gtk_marshal_NONE__POINTER
|
||||
#define gst_marshal_VOID__OBJECT_POINTER gtk_marshal_NONE__POINTER_POINTER
|
||||
#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT
|
||||
#define gst_marshal_VOID__OBJECT gtk_marshal_NONE__POINTER
|
||||
#define gst_marshal_VOID__OBJECT_POINTER gtk_marshal_NONE__POINTER_POINTER
|
||||
#define gst_marshal_VOID__INT_INT gtk_marshal_NONE__INT_INT
|
||||
|
||||
/* General macros */
|
||||
#ifdef __cplusplus
|
||||
|
@ -217,6 +223,10 @@ gtk_signal_handler_pending ((GtkObject *)object,name,may_block)
|
|||
|
||||
gint* g_signal_list_ids (GType type, guint *n_ids);
|
||||
|
||||
// lists
|
||||
GSList* g_slist_delete_link (GSList *list, GSList *link) __attribute__ ((no_instrument_function));
|
||||
|
||||
|
||||
// arguments/parameters
|
||||
|
||||
// first define GValue and GParamSpec
|
||||
|
|
101
gst/gst.c
101
gst/gst.c
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "gst_private.h"
|
||||
|
||||
#include "gstversion.h"
|
||||
#include "gstcpu.h"
|
||||
#include "gsttype.h"
|
||||
#include "gstplugin.h"
|
||||
|
@ -38,6 +39,7 @@
|
|||
#endif
|
||||
|
||||
#define MAX_PATH_SPLIT 16
|
||||
#define GST_PLUGIN_SEPARATOR ","
|
||||
|
||||
gchar *_gst_progname;
|
||||
|
||||
|
@ -47,6 +49,9 @@ extern gboolean _gst_plugin_spew;
|
|||
|
||||
|
||||
static gboolean gst_init_check (int *argc, gchar ***argv);
|
||||
static void load_plugin_func (gpointer data, gpointer user_data);
|
||||
|
||||
static GSList *preload_plugins = NULL;
|
||||
|
||||
const gchar *g_log_domain_gstreamer = "GStreamer";
|
||||
|
||||
|
@ -105,7 +110,12 @@ gst_init (int *argc, char **argv[])
|
|||
|
||||
GST_INFO (GST_CAT_GST_INIT, "Initializing GStreamer Core Library");
|
||||
|
||||
gst_object_get_type ();
|
||||
gst_pad_get_type ();
|
||||
gst_real_pad_get_type ();
|
||||
gst_ghost_pad_get_type ();
|
||||
gst_elementfactory_get_type ();
|
||||
gst_element_get_type ();
|
||||
gst_typefactory_get_type ();
|
||||
#ifndef GST_DISABLE_AUTOPLUG
|
||||
gst_autoplugfactory_get_type ();
|
||||
|
@ -115,9 +125,17 @@ gst_init (int *argc, char **argv[])
|
|||
_gst_props_initialize ();
|
||||
_gst_caps_initialize ();
|
||||
_gst_plugin_initialize ();
|
||||
_gst_event_initialize ();
|
||||
_gst_buffer_initialize ();
|
||||
_gst_buffer_pool_initialize ();
|
||||
|
||||
/* if we need to preload plugins */
|
||||
if (preload_plugins) {
|
||||
g_slist_foreach (preload_plugins, load_plugin_func, NULL);
|
||||
g_slist_free (preload_plugins);
|
||||
preload_plugins = NULL;
|
||||
}
|
||||
|
||||
/* register some standard builtin types */
|
||||
gst_elementfactory_new ("bin", gst_bin_get_type (), &gst_bin_details);
|
||||
gst_elementfactory_new ("pipeline", gst_pipeline_get_type (), &gst_pipeline_details);
|
||||
|
@ -137,23 +155,23 @@ gst_init (int *argc, char **argv[])
|
|||
}
|
||||
|
||||
static void
|
||||
gst_add_paths_func (const gchar *pathlist)
|
||||
split_and_iterate (const gchar *stringlist, gchar *separator, GFunc iterator)
|
||||
{
|
||||
gchar **paths;
|
||||
gchar **strings;
|
||||
gint j = 0;
|
||||
gchar *lastpath = g_strdup (pathlist);
|
||||
gchar *lastlist = g_strdup (stringlist);
|
||||
|
||||
while (lastpath) {
|
||||
paths = g_strsplit (lastpath, G_SEARCHPATH_SEPARATOR_S, MAX_PATH_SPLIT);
|
||||
g_free (lastpath);
|
||||
lastpath = NULL;
|
||||
while (lastlist) {
|
||||
strings = g_strsplit (lastlist, separator, MAX_PATH_SPLIT);
|
||||
//strings = g_strsplit (lastlist, G_SEARCHPATH_SEPARATOR_S, MAX_PATH_SPLIT);
|
||||
g_free (lastlist);
|
||||
lastlist = NULL;
|
||||
|
||||
while (paths[j]) {
|
||||
GST_INFO (GST_CAT_GST_INIT, "Adding plugin path: \"%s\"", paths[j]);
|
||||
gst_plugin_add_path (paths[j]);
|
||||
while (strings[j]) {
|
||||
iterator (strings[j], NULL);
|
||||
if (++j == MAX_PATH_SPLIT) {
|
||||
lastpath = g_strdup (paths[j]);
|
||||
g_strfreev (paths);
|
||||
lastlist = g_strdup (strings[j]);
|
||||
g_strfreev (strings);
|
||||
j=0;
|
||||
break;
|
||||
}
|
||||
|
@ -161,6 +179,33 @@ gst_add_paths_func (const gchar *pathlist)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_path_func (gpointer data, gpointer user_data)
|
||||
{
|
||||
GST_INFO (GST_CAT_GST_INIT, "Adding plugin path: \"%s\"", (gchar *)data);
|
||||
gst_plugin_add_path ((gchar *)data);
|
||||
}
|
||||
|
||||
static void
|
||||
prepare_for_load_plugin_func (gpointer data, gpointer user_data)
|
||||
{
|
||||
preload_plugins = g_slist_prepend (preload_plugins, data);
|
||||
}
|
||||
|
||||
static void
|
||||
load_plugin_func (gpointer data, gpointer user_data)
|
||||
{
|
||||
gboolean ret;
|
||||
ret = gst_plugin_load ((gchar *)data);
|
||||
if (ret)
|
||||
GST_INFO (GST_CAT_GST_INIT, "Loaded plugin: \"%s\"", (gchar *)data);
|
||||
else
|
||||
GST_INFO (GST_CAT_GST_INIT, "Failed to load plugin: \"%s\"", (gchar *)data);
|
||||
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
|
||||
/* returns FALSE if the program can be aborted */
|
||||
static gboolean
|
||||
gst_init_check (int *argc,
|
||||
|
@ -226,7 +271,12 @@ gst_init_check (int *argc,
|
|||
(*argv)[i] = NULL;
|
||||
}
|
||||
else if (!strncmp ("--gst-plugin-path=", (*argv)[i], 17)) {
|
||||
gst_add_paths_func ((*argv)[i]+18);
|
||||
split_and_iterate ((*argv)[i]+18, G_SEARCHPATH_SEPARATOR_S, add_path_func);
|
||||
|
||||
(*argv)[i] = NULL;
|
||||
}
|
||||
else if (!strncmp ("--gst-plugin-load=", (*argv)[i], 17)) {
|
||||
split_and_iterate ((*argv)[i]+18, ",", prepare_for_load_plugin_func);
|
||||
|
||||
(*argv)[i] = NULL;
|
||||
}
|
||||
|
@ -257,7 +307,7 @@ gst_init_check (int *argc,
|
|||
/* check for ENV variables */
|
||||
{
|
||||
const gchar *plugin_path = g_getenv("GST_PLUGIN_PATH");
|
||||
gst_add_paths_func (plugin_path);
|
||||
split_and_iterate (plugin_path, G_SEARCHPATH_SEPARATOR_S, add_path_func);
|
||||
}
|
||||
|
||||
if (showhelp) {
|
||||
|
@ -272,6 +322,8 @@ gst_init_check (int *argc,
|
|||
g_print (" --gst-plugin-spew Enable printout of errors while loading GST plugins\n");
|
||||
g_print (" --gst-plugin-path=PATH Add directories separated with '%s' to the plugin search path\n",
|
||||
G_SEARCHPATH_SEPARATOR_S);
|
||||
g_print (" --gst-plugin-load=PLUGINS Load plugins separated with '%s'\n",
|
||||
GST_PLUGIN_SEPARATOR);
|
||||
|
||||
g_print ("\n Mask (to be OR'ed) info/debug FLAGS \n");
|
||||
g_print ("--------------------------------------------------------\n");
|
||||
|
@ -323,3 +375,24 @@ gst_main_quit (void)
|
|||
gtk_main_quit ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_version:
|
||||
* @major: pointer to a guint to store the major version number
|
||||
* @minor: pointer to a guint to store the minor version number
|
||||
* @micro: pointer to a guint to store the micro version number
|
||||
*
|
||||
* Gets the version number of the GStreamer library
|
||||
*/
|
||||
void
|
||||
gst_version (guint *major, guint *minor, guint *micro)
|
||||
{
|
||||
g_return_if_fail (major);
|
||||
g_return_if_fail (minor);
|
||||
g_return_if_fail (micro);
|
||||
|
||||
*major = GST_VERSION_MAJOR;
|
||||
*minor = GST_VERSION_MINOR;
|
||||
*micro = GST_VERSION_MICRO;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <gst/cothreads.h>
|
||||
#include <gst/gstscheduler.h>
|
||||
#include <gst/gsttimecache.h>
|
||||
#include <gst/gstevent.h>
|
||||
|
||||
#include <gst/gstparse.h>
|
||||
#include <gst/gstextratypes.h>
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
*/
|
||||
|
||||
//#define GST_DEBUG_ENABLED
|
||||
|
||||
#include <gst/gstconfig.h>
|
||||
|
||||
#include "gst_private.h"
|
||||
|
||||
#include "gstautoplug.h"
|
||||
|
@ -168,8 +171,10 @@ gst_autoplug_to_renderers (GstAutoplug *autoplug, GstCaps *srccaps, GstElement *
|
|||
static void gst_autoplugfactory_class_init (GstAutoplugFactoryClass *klass);
|
||||
static void gst_autoplugfactory_init (GstAutoplugFactory *factory);
|
||||
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
static xmlNodePtr gst_autoplugfactory_save_thyself (GstObject *object, xmlNodePtr parent);
|
||||
static void gst_autoplugfactory_restore_thyself (GstObject *object, xmlNodePtr parent);
|
||||
#endif
|
||||
|
||||
static GstPluginFeatureClass *factory_parent_class = NULL;
|
||||
//static guint gst_autoplugfactory_signals[LAST_SIGNAL] = { 0 };
|
||||
|
@ -211,8 +216,10 @@ gst_autoplugfactory_class_init (GstAutoplugFactoryClass *klass)
|
|||
|
||||
factory_parent_class = g_type_class_ref (GST_TYPE_PLUGIN_FEATURE);
|
||||
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_autoplugfactory_save_thyself);
|
||||
gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_autoplugfactory_restore_thyself);
|
||||
#endif
|
||||
|
||||
_gst_autoplugfactories = NULL;
|
||||
}
|
||||
|
@ -361,6 +368,7 @@ gst_autoplugfactory_make (const gchar *name)
|
|||
return gst_autoplugfactory_create (factory);;
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
static xmlNodePtr
|
||||
gst_autoplugfactory_save_thyself (GstObject *object, xmlNodePtr parent)
|
||||
{
|
||||
|
@ -407,3 +415,4 @@ gst_autoplugfactory_restore_thyself (GstObject *object, xmlNodePtr parent)
|
|||
children = children->next;
|
||||
}
|
||||
}
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
|
|
15
gst/gstbin.c
15
gst/gstbin.c
|
@ -113,16 +113,17 @@ gst_bin_class_init (GstBinClass *klass)
|
|||
gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
|
||||
GST_TYPE_ELEMENT);
|
||||
|
||||
klass->change_state_type = gst_bin_change_state_type;
|
||||
klass->iterate = gst_bin_iterate_func;
|
||||
klass->change_state_type = GST_DEBUG_FUNCPTR (gst_bin_change_state_type);
|
||||
klass->iterate = GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
gstobject_class->save_thyself = gst_bin_save_thyself;
|
||||
gstobject_class->restore_thyself = gst_bin_restore_thyself;
|
||||
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
|
||||
gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
|
||||
#endif
|
||||
|
||||
gstelement_class->change_state = gst_bin_change_state;
|
||||
gobject_class->dispose = gst_bin_dispose;
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
|
||||
|
||||
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -644,7 +645,7 @@ gst_bin_restore_thyself (GstObject *object,
|
|||
field = field->next;
|
||||
}
|
||||
}
|
||||
#endif // GST_DISABLE_LOADSAVE
|
||||
#endif /* GST_DISABLE_LOADSAVE */
|
||||
|
||||
|
||||
/**
|
||||
|
|
134
gst/gstbuffer.c
134
gst/gstbuffer.c
|
@ -27,6 +27,8 @@
|
|||
#include "gstbuffer.h"
|
||||
|
||||
|
||||
GType _gst_buffer_type;
|
||||
|
||||
static GMemChunk *_gst_buffer_chunk;
|
||||
static GMutex *_gst_buffer_chunk_lock;
|
||||
|
||||
|
@ -34,6 +36,17 @@ void
|
|||
_gst_buffer_initialize (void)
|
||||
{
|
||||
int buffersize = sizeof(GstBuffer);
|
||||
static const GTypeInfo buffer_info = {
|
||||
0, // sizeof(class),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0, // sizeof(object),
|
||||
0,
|
||||
NULL,
|
||||
};
|
||||
|
||||
// round up to the nearest 32 bytes for cache-line and other efficiencies
|
||||
buffersize = (((buffersize-1) / 32) + 1) * 32;
|
||||
|
@ -42,6 +55,8 @@ _gst_buffer_initialize (void)
|
|||
buffersize * 32, G_ALLOC_AND_FREE);
|
||||
|
||||
_gst_buffer_chunk_lock = g_mutex_new ();
|
||||
|
||||
_gst_buffer_type = g_type_register_static (G_TYPE_INT, "GstBuffer", &buffer_info, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,7 +67,7 @@ _gst_buffer_initialize (void)
|
|||
* Returns: new buffer
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_new(void)
|
||||
gst_buffer_new (void)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
|
||||
|
@ -61,6 +76,8 @@ gst_buffer_new(void)
|
|||
g_mutex_unlock (_gst_buffer_chunk_lock);
|
||||
GST_INFO (GST_CAT_BUFFER,"creating new buffer %p",buffer);
|
||||
|
||||
GST_DATA_TYPE(buffer) = _gst_buffer_type;
|
||||
|
||||
buffer->lock = g_mutex_new ();
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
atomic_set (&buffer->refcount, 1);
|
||||
|
@ -78,7 +95,7 @@ gst_buffer_new(void)
|
|||
buffer->pool_private = NULL;
|
||||
buffer->free = NULL;
|
||||
buffer->copy = NULL;
|
||||
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -91,18 +108,21 @@ gst_buffer_new(void)
|
|||
* Returns: new buffer
|
||||
*/
|
||||
GstBuffer*
|
||||
gst_buffer_new_from_pool (GstBufferPool *pool, guint64 location, gint size)
|
||||
gst_buffer_new_from_pool (GstBufferPool *pool, guint32 offset, guint32 size)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
|
||||
g_return_val_if_fail (pool != NULL, NULL);
|
||||
g_return_val_if_fail (pool->buffer_new != NULL, NULL);
|
||||
|
||||
buffer = pool->buffer_new (pool, location, size, pool->user_data);
|
||||
buffer = pool->buffer_new (pool, offset, size, pool->user_data);
|
||||
buffer->pool = pool;
|
||||
buffer->free = pool->buffer_free;
|
||||
buffer->copy = pool->buffer_copy;
|
||||
|
||||
GST_INFO (GST_CAT_BUFFER,"creating new buffer %p from pool %p (size %x, offset %x)",
|
||||
buffer, pool, size, offset);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -124,13 +144,16 @@ gst_buffer_create_sub (GstBuffer *parent,
|
|||
GstBuffer *buffer;
|
||||
|
||||
g_return_val_if_fail (parent != NULL, NULL);
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT(parent) > 0, NULL);
|
||||
g_return_val_if_fail (size > 0, NULL);
|
||||
g_return_val_if_fail ((offset+size) <= parent->size, NULL);
|
||||
|
||||
g_mutex_lock (_gst_buffer_chunk_lock);
|
||||
buffer = g_mem_chunk_alloc (_gst_buffer_chunk);
|
||||
GST_DATA_TYPE(buffer) = _gst_buffer_type;
|
||||
g_mutex_unlock (_gst_buffer_chunk_lock);
|
||||
GST_INFO (GST_CAT_BUFFER,"creating new subbuffer %p from parent %p", buffer, parent);
|
||||
GST_INFO (GST_CAT_BUFFER,"creating new subbuffer %p from parent %p (size %u, offset %u)",
|
||||
buffer, parent, size, offset);
|
||||
|
||||
buffer->lock = g_mutex_new ();
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
|
@ -166,7 +189,7 @@ gst_buffer_create_sub (GstBuffer *parent,
|
|||
gst_buffer_ref (parent);
|
||||
|
||||
buffer->pool = NULL;
|
||||
// return the new subbuffer
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -192,6 +215,8 @@ gst_buffer_append (GstBuffer *buffer,
|
|||
g_return_val_if_fail (buffer != NULL, NULL);
|
||||
g_return_val_if_fail (append != NULL, NULL);
|
||||
g_return_val_if_fail (buffer->pool == NULL, NULL);
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0, NULL);
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT(append) > 0, NULL);
|
||||
|
||||
GST_INFO (GST_CAT_BUFFER,"appending buffers %p and %p",buffer,append);
|
||||
|
||||
|
@ -226,12 +251,15 @@ gst_buffer_append (GstBuffer *buffer,
|
|||
*
|
||||
* destroy the buffer
|
||||
*/
|
||||
void gst_buffer_destroy (GstBuffer *buffer)
|
||||
void
|
||||
gst_buffer_destroy (GstBuffer *buffer)
|
||||
{
|
||||
|
||||
g_return_if_fail (buffer != NULL);
|
||||
|
||||
GST_INFO (GST_CAT_BUFFER,"freeing %sbuffer %p", (buffer->parent?"sub":""),buffer);
|
||||
GST_INFO (GST_CAT_BUFFER, "freeing %sbuffer %p",
|
||||
(buffer->parent?"sub":""),
|
||||
buffer);
|
||||
|
||||
// free the data only if there is some, DONTFREE isn't set, and not sub
|
||||
if (GST_BUFFER_DATA (buffer) &&
|
||||
|
@ -252,6 +280,11 @@ void gst_buffer_destroy (GstBuffer *buffer)
|
|||
g_mutex_free (buffer->lock);
|
||||
//g_print("freed mutex\n");
|
||||
|
||||
#ifdef GST_DEBUG_ENABLED
|
||||
// make it hard to reuse by mistake
|
||||
memset (buffer, 0, sizeof (GstBuffer));
|
||||
#endif
|
||||
|
||||
// remove it entirely from memory
|
||||
g_mutex_lock (_gst_buffer_chunk_lock);
|
||||
g_mem_chunk_free (_gst_buffer_chunk,buffer);
|
||||
|
@ -268,44 +301,19 @@ void
|
|||
gst_buffer_ref (GstBuffer *buffer)
|
||||
{
|
||||
g_return_if_fail (buffer != NULL);
|
||||
g_return_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0);
|
||||
|
||||
GST_DEBUG (0,"referencing buffer %p\n", buffer);
|
||||
GST_INFO (GST_CAT_BUFFER, "ref buffer %p\n", buffer);
|
||||
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
//g_return_if_fail(atomic_read(&(buffer->refcount)) > 0);
|
||||
atomic_inc (&(buffer->refcount));
|
||||
#else
|
||||
g_return_if_fail (buffer->refcount > 0);
|
||||
GST_BUFFER_LOCK (buffer);
|
||||
buffer->refcount++;
|
||||
GST_BUFFER_UNLOCK (buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_ref_by_count:
|
||||
* @buffer: the GstBuffer to reference
|
||||
* @count: a number
|
||||
*
|
||||
* Increment the refcount of this buffer by the given number.
|
||||
*/
|
||||
void
|
||||
gst_buffer_ref_by_count (GstBuffer *buffer, int count)
|
||||
{
|
||||
g_return_if_fail (buffer != NULL);
|
||||
g_return_if_fail (count > 0);
|
||||
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
|
||||
atomic_add (count, &(buffer->refcount));
|
||||
#else
|
||||
g_return_if_fail (buffer->refcount > 0);
|
||||
GST_BUFFER_LOCK (buffer);
|
||||
buffer->refcount += count;
|
||||
GST_BUFFER_UNLOCK (buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_buffer_unref:
|
||||
* @buffer: the GstBuffer to unref
|
||||
|
@ -319,14 +327,13 @@ gst_buffer_unref (GstBuffer *buffer)
|
|||
gint zero;
|
||||
|
||||
g_return_if_fail (buffer != NULL);
|
||||
g_return_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0);
|
||||
|
||||
GST_DEBUG (0,"unreferencing buffer %p\n", buffer);
|
||||
GST_INFO (GST_CAT_BUFFER, "unref buffer %p\n", buffer);
|
||||
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
g_return_if_fail (atomic_read (&(buffer->refcount)) > 0);
|
||||
zero = atomic_dec_and_test (&(buffer->refcount));
|
||||
#else
|
||||
g_return_if_fail (buffer->refcount > 0);
|
||||
GST_BUFFER_LOCK (buffer);
|
||||
buffer->refcount--;
|
||||
zero = (buffer->refcount == 0);
|
||||
|
@ -352,6 +359,8 @@ gst_buffer_copy (GstBuffer *buffer)
|
|||
{
|
||||
GstBuffer *newbuf;
|
||||
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT(buffer) > 0, NULL);
|
||||
|
||||
// if a copy function exists, use it, else copy the bytes
|
||||
if (buffer->copy != NULL) {
|
||||
newbuf = (buffer->copy)(buffer);
|
||||
|
@ -391,7 +400,11 @@ gst_buffer_copy (GstBuffer *buffer)
|
|||
gboolean
|
||||
gst_buffer_is_span_fast (GstBuffer *buf1, GstBuffer *buf2)
|
||||
{
|
||||
return ((buf1->parent == buf2->parent) &&
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf1) > 0, FALSE);
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf2) > 0, FALSE);
|
||||
|
||||
return (buf1->parent && buf2->parent &&
|
||||
(buf1->parent == buf2->parent) &&
|
||||
((buf1->data + buf1->size) == buf2->data));
|
||||
}
|
||||
|
||||
|
@ -420,38 +433,43 @@ gst_buffer_span (GstBuffer *buf1, guint32 offset, GstBuffer *buf2, guint32 len)
|
|||
{
|
||||
GstBuffer *newbuf;
|
||||
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf1) > 0, NULL);
|
||||
g_return_val_if_fail (GST_BUFFER_REFCOUNT(buf2) > 0, NULL);
|
||||
|
||||
// make sure buf1 has a lower address than buf2
|
||||
if (buf1->data > buf2->data) {
|
||||
GstBuffer *tmp = buf1;
|
||||
g_print ("swapping buffers\n");
|
||||
buf1 = buf2;
|
||||
buf2 = tmp;
|
||||
}
|
||||
|
||||
// if the two buffers have the same parent and are adjacent
|
||||
// if ((buf1->parent == buf2->parent) &&
|
||||
// ((buf1->data + buf1->size) == buf2->data)) {
|
||||
if (gst_buffer_is_span_fast(buf1,buf2)) {
|
||||
// we simply create a subbuffer of the common parent
|
||||
return gst_buffer_create_sub(buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
|
||||
newbuf = gst_buffer_create_sub (buf1->parent, buf1->data - (buf1->parent->data) + offset, len);
|
||||
}
|
||||
else {
|
||||
g_print ("slow path taken in buffer_span\n");
|
||||
// otherwise we simply have to brute-force copy the buffers
|
||||
newbuf = gst_buffer_new ();
|
||||
|
||||
// otherwise we simply have to brute-force copy the buffers
|
||||
newbuf = gst_buffer_new();
|
||||
// put in new size
|
||||
newbuf->size = len;
|
||||
// allocate space for the copy
|
||||
newbuf->data = (guchar *)g_malloc(len);
|
||||
// copy the first buffer's data across
|
||||
memcpy(newbuf->data, buf1->data + offset, buf1->size - offset);
|
||||
// copy the second buffer's data across
|
||||
memcpy(newbuf->data + (buf1->size - offset), buf2->data, len - (buf1->size - offset));
|
||||
|
||||
// put in new size
|
||||
newbuf->size = len;
|
||||
// allocate space for the copy
|
||||
newbuf->data = (guchar *)g_malloc(len);
|
||||
// copy the first buffer's data across
|
||||
memcpy(newbuf->data, buf1->data + offset, buf1->size - offset);
|
||||
// copy the second buffer's data across
|
||||
memcpy(newbuf->data + offset, buf2->data, len - (buf1->size - offset));
|
||||
if (newbuf->offset != -1)
|
||||
newbuf->offset = buf1->offset + offset;
|
||||
newbuf->timestamp = buf1->timestamp;
|
||||
if (buf2->maxage > buf1->maxage) newbuf->maxage = buf2->maxage;
|
||||
else newbuf->maxage = buf1->maxage;
|
||||
|
||||
if (newbuf->offset != -1)
|
||||
newbuf->offset = buf1->offset + offset;
|
||||
newbuf->timestamp = buf1->timestamp;
|
||||
if (buf2->maxage > buf1->maxage) newbuf->maxage = buf2->maxage;
|
||||
else newbuf->maxage = buf1->maxage;
|
||||
}
|
||||
|
||||
return newbuf;
|
||||
}
|
||||
|
@ -475,5 +493,5 @@ GstBuffer *
|
|||
gst_buffer_merge (GstBuffer *buf1, GstBuffer *buf2)
|
||||
{
|
||||
// we're just a specific case of the more general gst_buffer_span()
|
||||
return gst_buffer_span(buf1, 0, buf2, buf1->size + buf2->size);
|
||||
return gst_buffer_span (buf1, 0, buf2, buf1->size + buf2->size);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,18 @@
|
|||
#ifndef __GST_BUFFER_H__
|
||||
#define __GST_BUFFER_H__
|
||||
|
||||
//
|
||||
// Define this to add file:line info to each GstBuffer showing
|
||||
// the location in the source code where the buffer was created.
|
||||
//
|
||||
// #define GST_BUFFER_WHERE
|
||||
//
|
||||
// Then in gdb, you can `call gst_buffer_print_live()' to get a list
|
||||
// of allocated GstBuffers and also the file:line where they were
|
||||
// allocated.
|
||||
//
|
||||
|
||||
#include <gst/gstdata.h>
|
||||
#include <gst/gstobject.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -39,18 +51,16 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
extern GType _gst_buffer_type;
|
||||
|
||||
#define GST_BUFFER(buf) \
|
||||
((GstBuffer *)(buf))
|
||||
#define GST_TYPE_BUFFER (_gst_buffer_type)
|
||||
#define GST_BUFFER(buf) ((GstBuffer *)(buf))
|
||||
#define GST_IS_BUFFER(buf) (GST_DATA_TYPE(buf) == GST_TYPE_BUFFER)
|
||||
|
||||
#define GST_BUFFER_FLAGS(buf) \
|
||||
(GST_BUFFER(buf)->flags)
|
||||
#define GST_BUFFER_FLAG_IS_SET(buf,flag) \
|
||||
(GST_BUFFER_FLAGS(buf) & (1<<(flag)))
|
||||
#define GST_BUFFER_FLAG_SET(buf,flag) \
|
||||
G_STMT_START{ (GST_BUFFER_FLAGS(buf) |= (1<<(flag))); }G_STMT_END
|
||||
#define GST_BUFFER_FLAG_UNSET(buf,flag) \
|
||||
G_STMT_START{ (GST_BUFFER_FLAGS(buf) &= ~(1<<(flag))); }G_STMT_END
|
||||
#define GST_BUFFER_FLAGS(buf) (GST_BUFFER(buf)->flags)
|
||||
#define GST_BUFFER_FLAG_IS_SET(buf,flag) (GST_BUFFER_FLAGS(buf) & (1<<(flag)))
|
||||
#define GST_BUFFER_FLAG_SET(buf,flag) G_STMT_START{ (GST_BUFFER_FLAGS(buf) |= (1<<(flag))); }G_STMT_END
|
||||
#define GST_BUFFER_FLAG_UNSET(buf,flag) G_STMT_START{ (GST_BUFFER_FLAGS(buf) &= ~(1<<(flag))); }G_STMT_END
|
||||
|
||||
|
||||
#define GST_BUFFER_DATA(buf) (GST_BUFFER(buf)->data)
|
||||
|
@ -82,7 +92,6 @@ typedef enum {
|
|||
} GstBufferFlags;
|
||||
|
||||
|
||||
|
||||
typedef struct _GstBuffer GstBuffer;
|
||||
|
||||
|
||||
|
@ -93,56 +102,56 @@ typedef GstBuffer *(*GstBufferCopyFunc) (GstBuffer *srcbuf);
|
|||
#include <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 */
|
||||
|
|
|
@ -274,6 +274,13 @@ gst_buffer_pool_destroy (GstBufferPool *pool)
|
|||
g_free(pool);
|
||||
}
|
||||
|
||||
//
|
||||
// This is so we don't get messed up by GST_BUFFER_WHERE.
|
||||
//
|
||||
static GstBuffer *
|
||||
_pool_gst_buffer_copy (GstBuffer *buffer)
|
||||
{ return gst_buffer_copy (buffer); }
|
||||
|
||||
/**
|
||||
* gst_buffer_pool_get_default:
|
||||
* @buffer_size: the number of bytes this buffer will store
|
||||
|
@ -314,7 +321,7 @@ gst_buffer_pool_get_default (guint buffer_size, guint pool_size)
|
|||
pool = gst_buffer_pool_new();
|
||||
gst_buffer_pool_set_buffer_new_function (pool, gst_buffer_pool_default_buffer_new);
|
||||
gst_buffer_pool_set_buffer_free_function (pool, gst_buffer_pool_default_buffer_free);
|
||||
gst_buffer_pool_set_buffer_copy_function (pool, gst_buffer_copy);
|
||||
gst_buffer_pool_set_buffer_copy_function (pool, _pool_gst_buffer_copy);
|
||||
gst_buffer_pool_set_destroy_hook (pool, gst_buffer_pool_default_destroy_hook);
|
||||
|
||||
def = g_new0 (GstBufferPoolDefault, 1);
|
||||
|
|
|
@ -545,7 +545,7 @@ gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
#if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) )
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
/**
|
||||
* gst_caps_save_thyself:
|
||||
* @caps: a capabilty to save
|
||||
|
@ -629,4 +629,4 @@ gst_caps_load_thyself (xmlNodePtr parent)
|
|||
return result;
|
||||
}
|
||||
|
||||
#endif /* (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) ) */
|
||||
#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
|
||||
|
|
|
@ -24,14 +24,7 @@
|
|||
#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>
|
||||
|
||||
|
@ -118,7 +111,9 @@ GstCaps* gst_caps_prepend (GstCaps *caps, GstCaps *capstoadd);
|
|||
|
||||
gboolean gst_caps_check_compatibility (GstCaps *fromcaps, GstCaps *tocaps);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlNodePtr gst_caps_save_thyself (GstCaps *caps, xmlNodePtr parent);
|
||||
GstCaps* gst_caps_load_thyself (xmlNodePtr parent);
|
||||
#endif
|
||||
|
||||
#endif /* __GST_CAPS_H__ */
|
||||
|
|
32
gst/gstconfig.h
Normal file
32
gst/gstconfig.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* This header interprets the various GST_* macros that are typically *
|
||||
* provided by the gstreamer-config or gstreamer.pc files. */
|
||||
|
||||
#ifndef __GST_CONFIG_H__
|
||||
#define __GST_CONFIG_H__
|
||||
|
||||
|
||||
/***** We include config.h in case someone perhaps used a gstreamer.m4 or
|
||||
something else that provides funky overrides. BEWARE! *****/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
|
||||
/***** Deal with XML stuff, we have to handle both loadsave and registry *****/
|
||||
|
||||
#if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) )
|
||||
#include <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__ */
|
46
gst/gstdata.h
Normal file
46
gst/gstdata.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/* 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__ */
|
|
@ -65,13 +65,14 @@ static xmlNodePtr gst_element_save_thyself (GstObject *object, xmlNodePtr paren
|
|||
GstElement* gst_element_restore_thyself (xmlNodePtr self, GstObject *parent);
|
||||
#endif
|
||||
|
||||
GType _gst_element_type = 0;
|
||||
|
||||
static GstObjectClass *parent_class = NULL;
|
||||
static guint gst_element_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
GType gst_element_get_type(void) {
|
||||
static GType element_type = 0;
|
||||
|
||||
if (!element_type) {
|
||||
GType gst_element_get_type (void)
|
||||
{
|
||||
if (!_gst_element_type) {
|
||||
static const GTypeInfo element_info = {
|
||||
sizeof(GstElementClass),
|
||||
(GBaseInitFunc)gst_element_base_class_init,
|
||||
|
@ -84,9 +85,9 @@ GType gst_element_get_type(void) {
|
|||
(GInstanceInitFunc)gst_element_init,
|
||||
NULL
|
||||
};
|
||||
element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement", &element_info, G_TYPE_FLAG_ABSTRACT);
|
||||
_gst_element_type = g_type_register_static(GST_TYPE_OBJECT, "GstElement", &element_info, G_TYPE_FLAG_ABSTRACT);
|
||||
}
|
||||
return element_type;
|
||||
return _gst_element_type;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -602,14 +603,14 @@ gst_element_get_padtemplate_by_compatible (GstElement *element, GstPadTemplate *
|
|||
}
|
||||
|
||||
static GstPad*
|
||||
gst_element_request_pad (GstElement *element, GstPadTemplate *templ)
|
||||
gst_element_request_pad (GstElement *element, GstPadTemplate *templ, const gchar* name)
|
||||
{
|
||||
GstPad *newpad = NULL;
|
||||
GstElementClass *oclass;
|
||||
|
||||
oclass = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS(element));
|
||||
if (oclass->request_new_pad)
|
||||
newpad = (oclass->request_new_pad)(element, templ);
|
||||
newpad = (oclass->request_new_pad)(element, templ, name);
|
||||
|
||||
return newpad;
|
||||
}
|
||||
|
@ -638,7 +639,7 @@ gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
|
|||
|
||||
templ_new = gst_element_get_padtemplate_by_compatible (element, templ);
|
||||
if (templ_new != NULL)
|
||||
pad = gst_element_request_pad (element, templ_new);
|
||||
pad = gst_element_request_pad (element, templ_new, NULL);
|
||||
|
||||
return pad;
|
||||
}
|
||||
|
@ -658,19 +659,40 @@ gst_element_request_compatible_pad (GstElement *element, GstPadTemplate *templ)
|
|||
GstPad*
|
||||
gst_element_request_pad_by_name (GstElement *element, const gchar *name)
|
||||
{
|
||||
GstPadTemplate *templ;
|
||||
GstPadTemplate *templ = NULL;
|
||||
GstPad *pad;
|
||||
const gchar *req_name = NULL;
|
||||
gboolean templ_found = FALSE;
|
||||
GList *list;
|
||||
gint n;
|
||||
|
||||
g_return_val_if_fail (element != NULL, NULL);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (element), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
templ = gst_element_get_padtemplate_by_name (element, name);
|
||||
if (strstr (name, "%d")) {
|
||||
templ = gst_element_get_padtemplate_by_name (element, name);
|
||||
req_name = NULL;
|
||||
} else {
|
||||
list = gst_element_get_padtemplate_list(element);
|
||||
while (!templ_found && list) {
|
||||
templ = (GstPadTemplate*) list->data;
|
||||
if (strstr (templ->name_template, "%d")) {
|
||||
if (sscanf(name, templ->name_template, &n)) {
|
||||
templ_found = TRUE;
|
||||
req_name = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (templ == NULL)
|
||||
return NULL;
|
||||
|
||||
pad = gst_element_request_pad (element, templ);
|
||||
|
||||
return NULL;
|
||||
|
||||
pad = gst_element_request_pad (element, templ, req_name);
|
||||
|
||||
return pad;
|
||||
}
|
||||
|
||||
|
@ -772,6 +794,14 @@ gst_element_error (GstElement *element, const gchar *error)
|
|||
}
|
||||
|
||||
|
||||
GstElementState
|
||||
gst_element_get_state (GstElement *elem)
|
||||
{
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (elem), GST_STATE_VOID_PENDING);
|
||||
|
||||
return GST_STATE (elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_element_set_state:
|
||||
* @element: element to change state of
|
||||
|
@ -836,7 +866,6 @@ gst_element_set_state (GstElement *element, GstElementState state)
|
|||
}
|
||||
}
|
||||
|
||||
/* this is redundant, really, it will always return SUCCESS */
|
||||
return return_val;
|
||||
}
|
||||
|
||||
|
@ -1157,7 +1186,7 @@ gst_element_restore_thyself (xmlNodePtr self, GstObject *parent)
|
|||
|
||||
return element;
|
||||
}
|
||||
#endif // GST_DISABLE_LOADSAVE
|
||||
#endif /* GST_DISABLE_LOADSAVE */
|
||||
|
||||
/**
|
||||
* gst_element_set_sched:
|
||||
|
|
|
@ -24,14 +24,7 @@
|
|||
#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>
|
||||
|
@ -72,16 +65,22 @@ typedef enum {
|
|||
#define GST_STATE_PAUSED_TO_READY ((GST_STATE_PAUSED<<8) | GST_STATE_READY)
|
||||
#define GST_STATE_READY_TO_NULL ((GST_STATE_READY<<8) | GST_STATE_NULL)
|
||||
|
||||
#define GST_TYPE_ELEMENT \
|
||||
(gst_element_get_type())
|
||||
#define GST_ELEMENT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ELEMENT,GstElement))
|
||||
#define GST_ELEMENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ELEMENT,GstElementClass))
|
||||
#define GST_IS_ELEMENT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ELEMENT))
|
||||
#define GST_IS_ELEMENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENT))
|
||||
extern GType _gst_element_type;
|
||||
|
||||
#define GST_TYPE_ELEMENT (_gst_element_type)
|
||||
|
||||
#define GST_ELEMENT_FAST(obj) ((GstElement*)(obj))
|
||||
#define GST_ELEMENT_CLASS_FAST(klass) ((GstElementClass*)(klass))
|
||||
#define GST_IS_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_ELEMENT))
|
||||
#define GST_IS_ELEMENT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_ELEMENT))
|
||||
|
||||
#ifdef GST_TYPE_PARANOID
|
||||
# define GST_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_ELEMENT, GstElement))
|
||||
# define GST_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_ELEMENT, GstElementClass))
|
||||
#else
|
||||
# define GST_ELEMENT GST_ELEMENT_FAST
|
||||
# define GST_ELEMENT_CLASS GST_ELEMENT_CLASS_FAST
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
/* element is complex (for some def.) and generally require a cothread */
|
||||
|
@ -132,32 +131,32 @@ typedef struct _GstElementFactoryClass GstElementFactoryClass;
|
|||
typedef void (*GstElementLoopFunction) (GstElement *element);
|
||||
|
||||
struct _GstElement {
|
||||
GstObject object;
|
||||
|
||||
guint8 current_state;
|
||||
guint8 pending_state;
|
||||
GstObject object;
|
||||
|
||||
/* element state and scheduling */
|
||||
guint8 current_state;
|
||||
guint8 pending_state;
|
||||
GstElement *manager;
|
||||
GstSchedule *sched;
|
||||
GstElementLoopFunction loopfunc;
|
||||
cothread_state *threadstate;
|
||||
GstPad *select_pad;
|
||||
cothread_state *threadstate;
|
||||
|
||||
guint16 numpads;
|
||||
guint16 numsrcpads;
|
||||
guint16 numsinkpads;
|
||||
GList *pads;
|
||||
|
||||
GstElement *manager;
|
||||
GstSchedule *sched;
|
||||
/* element pads */
|
||||
guint16 numpads;
|
||||
guint16 numsrcpads;
|
||||
guint16 numsinkpads;
|
||||
GList *pads;
|
||||
GstPad *select_pad;
|
||||
};
|
||||
|
||||
struct _GstElementClass {
|
||||
GstObjectClass parent_class;
|
||||
GstObjectClass parent_class;
|
||||
|
||||
/* the elementfactory that created us */
|
||||
GstElementFactory *elementfactory;
|
||||
GstElementFactory *elementfactory;
|
||||
/* templates for our pads */
|
||||
GList *padtemplates;
|
||||
gint numpadtemplates;
|
||||
GList *padtemplates;
|
||||
gint numpadtemplates;
|
||||
|
||||
/* signal callbacks */
|
||||
void (*state_change) (GstElement *element,GstElementState state);
|
||||
|
@ -169,13 +168,13 @@ struct _GstElementClass {
|
|||
void (*eos) (GstElement *element);
|
||||
|
||||
/* local pointers for get/set */
|
||||
void (*set_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
void (*get_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
void (*set_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
void (*get_property) (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
|
||||
/* change the element state */
|
||||
GstElementStateReturn (*change_state) (GstElement *element);
|
||||
/* request a new pad */
|
||||
GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ);
|
||||
GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ, const gchar* name);
|
||||
};
|
||||
|
||||
void gst_element_class_add_padtemplate (GstElementClass *element, GstPadTemplate *templ);
|
||||
|
@ -215,6 +214,7 @@ void gst_element_disconnect (GstElement *src, const gchar *srcpadname,
|
|||
void gst_element_signal_eos (GstElement *element);
|
||||
|
||||
|
||||
GstElementState gst_element_get_state (GstElement *elem);
|
||||
/* called by the app to set the state of the element */
|
||||
gint gst_element_set_state (GstElement *element, GstElementState state);
|
||||
const gchar * gst_element_statename (GstElementState state);
|
||||
|
@ -223,8 +223,10 @@ void gst_element_error (GstElement *element, const gchar *error);
|
|||
|
||||
GstElementFactory* gst_element_get_factory (GstElement *element);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
/* XML write and read */
|
||||
GstElement* gst_element_restore_thyself (xmlNodePtr self, GstObject *parent);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
@ -243,16 +245,13 @@ struct _GstElementDetails {
|
|||
gchar *copyright; /* copyright details (year, etc.) */
|
||||
};
|
||||
|
||||
#define GST_TYPE_ELEMENTFACTORY \
|
||||
(gst_elementfactory_get_type())
|
||||
#define GST_ELEMENTFACTORY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ELEMENTFACTORY,GstElementFactory))
|
||||
#define GST_ELEMENTFACTORY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ELEMENTFACTORY,GstElementFactoryClass))
|
||||
#define GST_IS_ELEMENTFACTORY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ELEMENTFACTORY))
|
||||
#define GST_IS_ELEMENTFACTORY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENTFACTORY))
|
||||
#define GST_TYPE_ELEMENTFACTORY (gst_elementfactory_get_type())
|
||||
#define GST_ELEMENTFACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ELEMENTFACTORY,\
|
||||
GstElementFactory))
|
||||
#define GST_ELEMENTFACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ELEMENTFACTORY,\
|
||||
GstElementFactoryClass))
|
||||
#define GST_IS_ELEMENTFACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ELEMENTFACTORY))
|
||||
#define GST_IS_ELEMENTFACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ELEMENTFACTORY))
|
||||
|
||||
struct _GstElementFactory {
|
||||
GstPluginFeature feature;
|
||||
|
|
|
@ -31,7 +31,7 @@ static void gst_elementfactory_init (GstElementFactory *factory);
|
|||
#ifndef GST_DISABLE_REGISTRY
|
||||
static void gst_elementfactory_restore_thyself (GstObject *object, xmlNodePtr parent);
|
||||
static xmlNodePtr gst_elementfactory_save_thyself (GstObject *object, xmlNodePtr parent);
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
#endif
|
||||
|
||||
static void gst_elementfactory_unload_thyself (GstPluginFeature *feature);
|
||||
|
||||
|
@ -81,7 +81,7 @@ gst_elementfactory_class_init (GstElementFactoryClass *klass)
|
|||
#ifndef GST_DISABLE_REGISTRY
|
||||
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_elementfactory_save_thyself);
|
||||
gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR (gst_elementfactory_restore_thyself);
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
#endif
|
||||
|
||||
gstpluginfeature_class->unload_thyself = GST_DEBUG_FUNCPTR (gst_elementfactory_unload_thyself);
|
||||
|
||||
|
|
96
gst/gstevent.c
Normal file
96
gst/gstevent.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* 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;
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
#define __GST_EVENT_H__
|
||||
|
||||
#include <gst/gstobject.h>
|
||||
#include <gst/gstdata.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -36,14 +37,57 @@ typedef enum {
|
|||
GST_EVENT_FLUSH,
|
||||
GST_EVENT_EMPTY,
|
||||
GST_EVENT_SEEK,
|
||||
GST_EVENT_DISCONTINUOUS
|
||||
} GstEventType;
|
||||
|
||||
extern GType _gst_event_type;
|
||||
|
||||
#define GST_TYPE_EVENT (_gst_event_type)
|
||||
#define GST_EVENT(event) ((GstEvent*)(event))
|
||||
#define GST_IS_EVENT(event) (GST_DATA_TYPE(event) == GST_TYPE_EVENT)
|
||||
|
||||
#define GST_EVENT_TYPE(event) (GST_EVENT(event)->type)
|
||||
#define GST_EVENT_TIMESTAMP(event) (GST_EVENT(event)->timstamp)
|
||||
|
||||
/* seek events */
|
||||
typedef enum {
|
||||
GST_SEEK_ANY,
|
||||
GST_SEEK_TIMEOFFSET,
|
||||
GST_SEEK_BYTEOFFSET
|
||||
} GstSeekType;
|
||||
|
||||
#define GST_EVENT_SEEK_TYPE(event) (GST_EVENT(event)->event_data.seek.type)
|
||||
#define GST_EVENT_SEEK_OFFSET(event) (GST_EVENT(event)->event_data.seek.offset)
|
||||
#define GST_EVENT_SEEK_FLUSH(event) (GST_EVENT(event)->event_data.seek.flush)
|
||||
|
||||
typedef struct _GstEvent GstEvent;
|
||||
|
||||
struct _GstEvent {
|
||||
GstEventType type;
|
||||
GstData data;
|
||||
|
||||
GstEventType type;
|
||||
guint64 timestamp;
|
||||
|
||||
union {
|
||||
struct {
|
||||
GstSeekType type;
|
||||
guint64 offset;
|
||||
gboolean flush;
|
||||
} seek;
|
||||
} event_data;
|
||||
};
|
||||
|
||||
void _gst_event_initialize (void);
|
||||
|
||||
GstEvent* gst_event_new (GstEventType type);
|
||||
void gst_event_free (GstEvent* event);
|
||||
|
||||
/* seek events */
|
||||
GstEvent* gst_event_new_seek (GstSeekType type, guint64 offset, gboolean flush);
|
||||
|
||||
/* flush events */
|
||||
#define gst_event_new_flush() gst_event_new(GST_EVENT_FLUSH)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -459,6 +459,8 @@ gst_default_error_handler (gchar *file, gchar *function,
|
|||
|
||||
/***** DEBUG system *****/
|
||||
GHashTable *__gst_function_pointers = NULL;
|
||||
// FIXME make this thread specific
|
||||
static GSList* stack_trace = NULL;
|
||||
|
||||
gchar *_gst_debug_nameof_funcptr (void *ptr) __attribute__ ((no_instrument_function));
|
||||
|
||||
|
@ -479,15 +481,52 @@ _gst_debug_nameof_funcptr (void *ptr)
|
|||
|
||||
|
||||
#ifdef GST_ENABLE_FUNC_INSTRUMENTATION
|
||||
|
||||
void __cyg_profile_func_enter(void *this_fn,void *call_site) __attribute__ ((no_instrument_function));
|
||||
void __cyg_profile_func_enter(void *this_fn,void *call_site) {
|
||||
GST_DEBUG(GST_CAT_CALL_TRACE, "entering function %s\n", _gst_debug_nameof_funcptr (this_fn));
|
||||
void __cyg_profile_func_enter(void *this_fn,void *call_site)
|
||||
{
|
||||
gchar *name = _gst_debug_nameof_funcptr (this_fn);
|
||||
gchar *site = _gst_debug_nameof_funcptr (call_site);
|
||||
|
||||
GST_DEBUG(GST_CAT_CALL_TRACE, "entering function %s from %s\n", name, site);
|
||||
stack_trace = g_slist_prepend (stack_trace, g_strdup_printf ("%8p in %s from %p (%s)", this_fn, name, call_site, site));
|
||||
|
||||
g_free (name);
|
||||
g_free (site);
|
||||
}
|
||||
|
||||
void __cyg_profile_func_exit(void *this_fn,void *call_site) __attribute__ ((no_instrument_function));
|
||||
void __cyg_profile_func_exit(void *this_fn,void *call_site) {
|
||||
GST_DEBUG(GST_CAT_CALL_TRACE, "leavinging function %s\n", _gst_debug_nameof_funcptr (this_fn));
|
||||
void __cyg_profile_func_exit(void *this_fn,void *call_site)
|
||||
{
|
||||
gchar *name = _gst_debug_nameof_funcptr (this_fn);
|
||||
|
||||
GST_DEBUG(GST_CAT_CALL_TRACE, "leaving function %s\n", name);
|
||||
g_free (stack_trace->data);
|
||||
stack_trace = g_slist_delete_link (stack_trace, stack_trace);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
void
|
||||
gst_debug_print_stack_trace (void)
|
||||
{
|
||||
GSList *walk = stack_trace;
|
||||
gint count = 0;
|
||||
|
||||
if (walk)
|
||||
walk = g_slist_next (walk);
|
||||
|
||||
while (walk) {
|
||||
gchar *name = (gchar *) walk->data;
|
||||
|
||||
g_print ("#%-2d %s\n", count++, name);
|
||||
|
||||
walk = g_slist_next (walk);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void
|
||||
gst_debug_print_stack_trace (void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* GST_ENABLE_FUNC_INTSTRUMENTATION */
|
||||
|
|
|
@ -341,6 +341,8 @@ _gst_debug_register_funcptr (void *ptr, gchar *ptrname)
|
|||
|
||||
gchar *_gst_debug_nameof_funcptr (void *ptr);
|
||||
|
||||
void gst_debug_print_stack_trace (void);
|
||||
|
||||
|
||||
|
||||
#endif /* __GSTINFO_H__ */
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
/* Object signals and args */
|
||||
enum {
|
||||
PARENT_SET,
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
OBJECT_SAVED,
|
||||
#endif
|
||||
LAST_SIGNAL
|
||||
|
@ -43,6 +43,8 @@ enum {
|
|||
SO_LAST_SIGNAL
|
||||
};
|
||||
|
||||
GType _gst_object_type = 0;
|
||||
|
||||
typedef struct _GstSignalObject GstSignalObject;
|
||||
typedef struct _GstSignalObjectClass GstSignalObjectClass;
|
||||
|
||||
|
@ -64,9 +66,7 @@ static guint gst_object_signals[LAST_SIGNAL] = { 0 };
|
|||
GType
|
||||
gst_object_get_type (void)
|
||||
{
|
||||
static GType object_type = 0;
|
||||
|
||||
if (!object_type) {
|
||||
if (!_gst_object_type) {
|
||||
static const GTypeInfo object_info = {
|
||||
sizeof (GstObjectClass),
|
||||
NULL,
|
||||
|
@ -79,9 +79,9 @@ gst_object_get_type (void)
|
|||
(GInstanceInitFunc) gst_object_init,
|
||||
NULL
|
||||
};
|
||||
object_type = g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, G_TYPE_FLAG_ABSTRACT);
|
||||
_gst_object_type = g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, G_TYPE_FLAG_ABSTRACT);
|
||||
}
|
||||
return object_type;
|
||||
return _gst_object_type;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -98,7 +98,7 @@ gst_object_class_init (GstObjectClass *klass)
|
|||
G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,G_TYPE_NONE,1,
|
||||
G_TYPE_OBJECT);
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
gst_object_signals[OBJECT_SAVED] =
|
||||
g_signal_new("object_saved", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL, NULL,
|
||||
|
@ -446,7 +446,7 @@ gst_object_check_uniqueness (GList *list, const gchar *name)
|
|||
}
|
||||
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
/**
|
||||
* gst_object_save_thyself:
|
||||
* @object: GstObject to save
|
||||
|
@ -496,7 +496,7 @@ gst_object_restore_thyself (GstObject *object, xmlNodePtr parent)
|
|||
if (oclass->restore_thyself)
|
||||
oclass->restore_thyself (object, parent);
|
||||
}
|
||||
#endif // GST_DISABLE_LOADSAVE
|
||||
#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
|
||||
|
||||
/**
|
||||
* gst_object_get_path_string:
|
||||
|
@ -577,9 +577,9 @@ struct _GstSignalObjectClass {
|
|||
GObjectClass parent_class;
|
||||
|
||||
/* signals */
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
void (*object_loaded) (GstSignalObject *object, GstObject *new, xmlNodePtr self);
|
||||
#endif /* GST_DISABLE_LOADSAVE */
|
||||
#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
|
||||
};
|
||||
|
||||
static GType
|
||||
|
@ -614,7 +614,7 @@ gst_signal_object_class_init (GstSignalObjectClass *klass)
|
|||
|
||||
parent_class = g_type_class_ref (G_TYPE_OBJECT);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
gst_signal_object_signals[SO_OBJECT_LOADED] =
|
||||
g_signal_new("object_loaded", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
|
||||
|
@ -648,7 +648,7 @@ gst_class_signal_connect (GstObjectClass *klass,
|
|||
return g_signal_connect (klass->signal_object, name, func, func_data);
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
/**
|
||||
* gst_class_signal_emit_by_name:
|
||||
* @object: the object that sends the signal
|
||||
|
@ -669,4 +669,4 @@ gst_class_signal_emit_by_name (GstObject *object,
|
|||
g_signal_emit_by_name (oclass->signal_object, name, object, self);
|
||||
}
|
||||
|
||||
#endif // GST_DISABLE_LOADSAVE
|
||||
#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
|
||||
|
|
|
@ -24,10 +24,7 @@
|
|||
#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__
|
||||
|
@ -36,15 +33,13 @@
|
|||
#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"
|
||||
|
||||
|
@ -52,17 +47,22 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
extern GType _gst_object_type;
|
||||
|
||||
#define GST_TYPE_OBJECT \
|
||||
(gst_object_get_type())
|
||||
#define GST_OBJECT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OBJECT,GstObject))
|
||||
#define GST_OBJECT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OBJECT,GstObjectClass))
|
||||
#define GST_IS_OBJECT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OBJECT))
|
||||
#define GST_IS_OBJECT_CLASS(obj) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OBJECT))
|
||||
#define GST_TYPE_OBJECT (_gst_object_type)
|
||||
# define GST_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OBJECT))
|
||||
# define GST_IS_OBJECT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OBJECT))
|
||||
|
||||
#define GST_OBJECT_FAST(obj) ((GstObject*)(obj))
|
||||
#define GST_OBJECT_CLASS_FAST(klass) ((GstObjectClass*)(klass))
|
||||
|
||||
#ifdef GST_TYPE_PARANOID
|
||||
# define GST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OBJECT, GstObject))
|
||||
# define GST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OBJECT, GstObjectClass))
|
||||
#else
|
||||
# define GST_OBJECT GST_OBJECT_FAST
|
||||
# define GST_OBJECT_CLASS GST_OBJECT_CLASS_FAST
|
||||
#endif
|
||||
|
||||
//typedef struct _GstObject GstObject;
|
||||
//typedef struct _GstObjectClass GstObjectClass;
|
||||
|
@ -76,40 +76,43 @@ typedef enum
|
|||
} GstObjectFlags;
|
||||
|
||||
struct _GstObject {
|
||||
GObject object;
|
||||
GObject object;
|
||||
|
||||
gchar *name;
|
||||
gchar *name;
|
||||
/* have to have a refcount for the object */
|
||||
#ifdef HAVE_ATOMIC_H
|
||||
atomic_t refcount;
|
||||
atomic_t refcount;
|
||||
#else
|
||||
int refcount;
|
||||
gint refcount;
|
||||
#endif
|
||||
|
||||
/* locking for all sorts of things (like the refcount) */
|
||||
GMutex *lock;
|
||||
|
||||
GMutex *lock;
|
||||
/* this objects parent */
|
||||
GstObject *parent;
|
||||
GstObject *parent;
|
||||
|
||||
guint32 flags;
|
||||
guint32 flags;
|
||||
};
|
||||
|
||||
struct _GstObjectClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
gchar *path_string_separator;
|
||||
GObject *signal_object;
|
||||
gchar *path_string_separator;
|
||||
GObject *signal_object;
|
||||
|
||||
/* signals */
|
||||
void (*parent_set) (GstObject *object, GstObject *parent);
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
void (*object_saved) (GstObject *object, xmlNodePtr parent);
|
||||
#endif
|
||||
|
||||
/* functions go here */
|
||||
void (*destroy) (GstObject *object);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
xmlNodePtr (*save_thyself) (GstObject *object, xmlNodePtr parent);
|
||||
void (*restore_thyself) (GstObject *object, xmlNodePtr self);
|
||||
#endif
|
||||
};
|
||||
|
||||
#define GST_FLAGS(obj) (GST_OBJECT (obj)->flags)
|
||||
|
@ -144,11 +147,12 @@ void gst_object_unparent (GstObject *object);
|
|||
|
||||
gboolean gst_object_check_uniqueness (GList *list, const gchar *name);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
xmlNodePtr gst_object_save_thyself (GstObject *object, xmlNodePtr parent);
|
||||
void gst_object_restore_thyself (GstObject *object, xmlNodePtr parent);
|
||||
void gst_object_restore_thyself (GstObject *object, xmlNodePtr parent);
|
||||
#else
|
||||
#pragma GCC poison gst_object_save_thyself
|
||||
#pragma GCC poison gst_object_restore_thyself
|
||||
#endif
|
||||
|
||||
/* refcounting */
|
||||
|
@ -166,7 +170,7 @@ guint gst_class_signal_connect (GstObjectClass *klass,
|
|||
gpointer func,
|
||||
gpointer func_data);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
void gst_class_signal_emit_by_name (GstObject *object,
|
||||
const gchar *name,
|
||||
xmlNodePtr self);
|
||||
|
|
60
gst/gstpad.c
60
gst/gstpad.c
|
@ -30,6 +30,7 @@
|
|||
#include "gstbin.h"
|
||||
#include "gstscheduler.h"
|
||||
|
||||
GType _gst_pad_type = 0;
|
||||
|
||||
/***** Start with the base GstPad class *****/
|
||||
static void gst_pad_class_init (GstPadClass *klass);
|
||||
|
@ -42,10 +43,9 @@ static xmlNodePtr gst_pad_save_thyself (GstObject *object, xmlNodePtr parent);
|
|||
static GstObject *pad_parent_class = NULL;
|
||||
|
||||
GType
|
||||
gst_pad_get_type(void) {
|
||||
static GType pad_type = 0;
|
||||
|
||||
if (!pad_type) {
|
||||
gst_pad_get_type(void)
|
||||
{
|
||||
if (!_gst_pad_type) {
|
||||
static const GTypeInfo pad_info = {
|
||||
sizeof(GstPadClass),
|
||||
NULL,
|
||||
|
@ -58,9 +58,9 @@ gst_pad_get_type(void) {
|
|||
(GInstanceInitFunc)gst_pad_init,
|
||||
NULL
|
||||
};
|
||||
pad_type = g_type_register_static(GST_TYPE_OBJECT, "GstPad", &pad_info, 0);
|
||||
_gst_pad_type = g_type_register_static(GST_TYPE_OBJECT, "GstPad", &pad_info, 0);
|
||||
}
|
||||
return pad_type;
|
||||
return _gst_pad_type;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -107,15 +107,14 @@ static void gst_real_pad_dispose (GObject *object);
|
|||
|
||||
static void gst_pad_push_func (GstPad *pad, GstBuffer *buf);
|
||||
|
||||
GType _gst_real_pad_type = 0;
|
||||
|
||||
static GstPad *real_pad_parent_class = NULL;
|
||||
static guint gst_real_pad_signals[REAL_LAST_SIGNAL] = { 0 };
|
||||
|
||||
GType
|
||||
gst_real_pad_get_type(void) {
|
||||
static GType pad_type = 0;
|
||||
|
||||
if (!pad_type) {
|
||||
if (!_gst_real_pad_type) {
|
||||
static const GTypeInfo pad_info = {
|
||||
sizeof(GstRealPadClass),
|
||||
NULL,
|
||||
|
@ -128,9 +127,9 @@ gst_real_pad_get_type(void) {
|
|||
(GInstanceInitFunc)gst_real_pad_init,
|
||||
NULL
|
||||
};
|
||||
pad_type = g_type_register_static(GST_TYPE_PAD, "GstRealPad", &pad_info, 0);
|
||||
_gst_real_pad_type = g_type_register_static(GST_TYPE_PAD, "GstRealPad", &pad_info, 0);
|
||||
}
|
||||
return pad_type;
|
||||
return _gst_real_pad_type;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1432,7 +1431,7 @@ gst_pad_ghost_save_thyself (GstPad *pad,
|
|||
|
||||
return self;
|
||||
}
|
||||
#endif // GST_DISABLE_LOADSAVE
|
||||
#endif /* GST_DISABLE_LOADSAVE */
|
||||
|
||||
#ifndef gst_pad_push
|
||||
/**
|
||||
|
@ -1881,6 +1880,7 @@ gst_pad_get_element_private (GstPad *pad)
|
|||
|
||||
|
||||
/***** ghost pads *****/
|
||||
GType _gst_ghost_pad_type = 0;
|
||||
|
||||
static void gst_ghost_pad_class_init (GstGhostPadClass *klass);
|
||||
static void gst_ghost_pad_init (GstGhostPad *pad);
|
||||
|
@ -1890,9 +1890,7 @@ static GstPad *ghost_pad_parent_class = NULL;
|
|||
|
||||
GType
|
||||
gst_ghost_pad_get_type(void) {
|
||||
static GType pad_type = 0;
|
||||
|
||||
if (!pad_type) {
|
||||
if (!_gst_ghost_pad_type) {
|
||||
static const GTypeInfo pad_info = {
|
||||
sizeof(GstGhostPadClass),
|
||||
NULL,
|
||||
|
@ -1905,9 +1903,9 @@ gst_ghost_pad_get_type(void) {
|
|||
(GInstanceInitFunc)gst_ghost_pad_init,
|
||||
NULL
|
||||
};
|
||||
pad_type = g_type_register_static(GST_TYPE_PAD, "GstGhostPad", &pad_info, 0);
|
||||
_gst_ghost_pad_type = g_type_register_static(GST_TYPE_PAD, "GstGhostPad", &pad_info, 0);
|
||||
}
|
||||
return pad_type;
|
||||
return _gst_ghost_pad_type;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1985,14 +1983,36 @@ gst_pad_event (GstPad *pad, GstEventType event, gint64 timestamp, guint32 data)
|
|||
GST_DEBUG(GST_CAT_EVENT, "have event %d on pad %s:%s\n",(gint)event,GST_DEBUG_PAD_NAME(pad));
|
||||
|
||||
peer = GST_RPAD_PEER(pad);
|
||||
if (GST_RPAD_EVENTFUNC(peer))
|
||||
handled = GST_RPAD_EVENTFUNC(peer) (peer, event, timestamp, data);
|
||||
if (GST_RPAD_EVENTFUNC(peer)) {
|
||||
//handled = GST_RPAD_EVENTFUNC(peer) (peer, event, timestamp, data);
|
||||
}
|
||||
else {
|
||||
GST_DEBUG(GST_CAT_EVENT, "there's no event function for peer %s:%s\n",GST_DEBUG_PAD_NAME(peer));
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
GST_DEBUG(GST_CAT_EVENT, "would proceed with default behavior here\n");
|
||||
gst_pad_event_default(peer,event, timestamp, data);
|
||||
//gst_pad_event_default(peer,event, timestamp, data);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_pad_send_event (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
gboolean handled = FALSE;
|
||||
|
||||
GST_DEBUG (GST_CAT_EVENT, "have event %d on pad %s:%s\n",
|
||||
GST_EVENT_TYPE (event), GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
if (GST_RPAD_EVENTFUNC (pad))
|
||||
handled = GST_RPAD_EVENTFUNC (pad) (pad, event);
|
||||
else {
|
||||
GST_DEBUG(GST_CAT_EVENT, "there's no event function for pad %s:%s\n", GST_DEBUG_PAD_NAME (pad));
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
GST_DEBUG(GST_CAT_EVENT, "would proceed with default behavior here\n");
|
||||
//gst_pad_event_default (pad, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
79
gst/gstpad.h
79
gst/gstpad.h
|
@ -24,14 +24,7 @@
|
|||
#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>
|
||||
|
@ -44,25 +37,70 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
extern GType _gst_pad_type;
|
||||
extern GType _gst_real_pad_type;
|
||||
extern GType _gst_ghost_pad_type;
|
||||
|
||||
#define GST_TYPE_PAD (gst_pad_get_type ())
|
||||
#define GST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PAD, GstPad))
|
||||
#define GST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PAD, GstPadClass))
|
||||
//#define GST_TYPE_PARANOID
|
||||
|
||||
/*
|
||||
* Pad base class
|
||||
*/
|
||||
#define GST_TYPE_PAD (_gst_pad_type)
|
||||
|
||||
#define GST_PAD_FAST(obj) ((GstPad*)(obj))
|
||||
#define GST_PAD_CLASS_FAST(klass) ((GstPadClass*)(klass))
|
||||
#define GST_IS_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PAD))
|
||||
#define GST_IS_PAD_FAST(obj) (G_OBJECT_TYPE(obj) == GST_TYPE_REAL_PAD || \
|
||||
G_OBJECT_TYPE(obj) == GST_TYPE_GHOST_PAD)
|
||||
#define GST_IS_PAD_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PAD))
|
||||
|
||||
#define GST_TYPE_REAL_PAD (gst_real_pad_get_type ())
|
||||
#define GST_REAL_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_REAL_PAD, GstRealPad))
|
||||
#define GST_REAL_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_REAL_PAD, GstRealPadClass))
|
||||
#ifdef GST_TYPE_PARANOID
|
||||
# define GST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PAD, GstPad))
|
||||
# define GST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PAD, GstPadClass))
|
||||
#else
|
||||
# define GST_PAD GST_PAD_FAST
|
||||
# define GST_PAD_CLASS GST_PAD_CLASS_FAST
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Real Pads
|
||||
*/
|
||||
#define GST_TYPE_REAL_PAD (_gst_real_pad_type)
|
||||
|
||||
#define GST_REAL_PAD_FAST(obj) ((GstRealPad*)(obj))
|
||||
#define GST_REAL_PAD_CLASS_FAST(klass) ((GstRealPadClass*)(klass))
|
||||
#define GST_IS_REAL_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_REAL_PAD))
|
||||
#define GST_IS_REAL_PAD_FAST(obj) (G_OBJECT_TYPE(obj) == GST_TYPE_REAL_PAD)
|
||||
#define GST_IS_REAL_PAD_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_REAL_PAD))
|
||||
|
||||
#define GST_TYPE_GHOST_PAD (gst_ghost_pad_get_type ())
|
||||
#define GST_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GHOST_PAD, GstGhostPad))
|
||||
#define GST_GHOST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GHOST_PAD, GstGhostPadClass))
|
||||
#ifdef GST_TYPE_PARANOID
|
||||
# define GST_REAL_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_REAL_PAD, GstRealPad))
|
||||
# define GST_REAL_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_REAL_PAD, GstRealPadClass))
|
||||
#else
|
||||
# define GST_REAL_PAD GST_REAL_PAD_FAST
|
||||
# define GST_REAL_PAD_CLASS GST_REAL_PAD_CLASS_FAST
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Ghost Pads
|
||||
*/
|
||||
#define GST_TYPE_GHOST_PAD (_gst_ghost_pad_type)
|
||||
|
||||
#define GST_GHOST_PAD_FAST(obj) ((GstGhostPad*)(obj))
|
||||
#define GST_GHOST_PAD_CLASS_FAST(klass) ((GstGhostPadClass*)(klass))
|
||||
#define GST_IS_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GHOST_PAD))
|
||||
#define GST_IS_GHOST_PAD_FAST(obj) (G_OBJECT_TYPE(obj) == GST_TYPE_GHOST_PAD)
|
||||
#define GST_IS_GHOST_PAD_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GHOST_PAD))
|
||||
|
||||
#ifdef GST_TYPE_PARANOID
|
||||
# define GST_GHOST_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GHOST_PAD, GstGhostPad))
|
||||
# define GST_GHOST_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_GHOST_PAD, GstGhostPadClass))
|
||||
#else
|
||||
# define GST_GHOST_PAD GST_GHOST_PAD_FAST
|
||||
# define GST_GHOST_PAD_CLASS GST_GHOST_PAD_CLASS_FAST
|
||||
#endif
|
||||
|
||||
|
||||
//typedef struct _GstPad GstPad;
|
||||
//typedef struct _GstPadClass GstPadClass;
|
||||
|
@ -92,7 +130,7 @@ typedef enum {
|
|||
* buf is the buffer being passed */
|
||||
typedef void (*GstPadChainFunction) (GstPad *pad,GstBuffer *buf);
|
||||
typedef GstBuffer* (*GstPadGetFunction) (GstPad *pad);
|
||||
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEventType event, gint64 timestamp, guint32 data);
|
||||
typedef gboolean (*GstPadEventFunction) (GstPad *pad, GstEvent *event);
|
||||
|
||||
typedef GstBuffer* (*GstPadGetRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
|
||||
typedef GstBuffer* (*GstPadPullRegionFunction) (GstPad *pad, GstRegionType type, guint64 offset, guint64 len);
|
||||
|
@ -375,12 +413,15 @@ FALSE )
|
|||
}G_STMT_END
|
||||
#endif
|
||||
|
||||
gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
|
||||
|
||||
GstBuffer* gst_pad_peek (GstPad *pad);
|
||||
GstPad* gst_pad_select (GList *padlist);
|
||||
GstPad* gst_pad_selectv (GstPad *pad, ...);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
void gst_pad_load_and_connect (xmlNodePtr self, GstObject *parent);
|
||||
#endif
|
||||
|
||||
|
||||
/* ghostpads */
|
||||
|
@ -397,8 +438,10 @@ GstPadTemplate* gst_padtemplate_new (gchar *name_template,
|
|||
GstCaps* gst_padtemplate_get_caps (GstPadTemplate *templ);
|
||||
GstCaps* gst_padtemplate_get_caps_by_name (GstPadTemplate *templ, const gchar *name);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlNodePtr gst_padtemplate_save_thyself (GstPadTemplate *templ, xmlNodePtr parent);
|
||||
GstPadTemplate* gst_padtemplate_load_thyself (xmlNodePtr parent);
|
||||
#endif
|
||||
|
||||
xmlNodePtr gst_pad_ghost_save_thyself (GstPad *pad,
|
||||
GstElement *bin,
|
||||
|
|
|
@ -299,7 +299,11 @@ gst_parse_launch_cmdline(int argc,char *argv[],GstBin *parent,gst_parse_priv *pr
|
|||
element = gst_elementfactory_make(arg,ptr);
|
||||
g_free(ptr);
|
||||
if (!element) {
|
||||
#ifndef GST_DISABLE_REGISTRY
|
||||
fprintf(stderr,"Couldn't create a '%s', no such element or need to run gstreamer-register?\n",arg);
|
||||
#else
|
||||
fprintf(stderr,"Couldn't create a '%s', no such element or need to load pluginn?\n",arg);
|
||||
#endif
|
||||
exit(-1);
|
||||
}
|
||||
GST_DEBUG(0,"CREATED element %s\n",GST_ELEMENT_NAME(element));
|
||||
|
|
|
@ -105,7 +105,7 @@ _gst_plugin_initialize (void)
|
|||
gst_plugin_load_thyself (doc->xmlRootNode);
|
||||
|
||||
xmlFreeDoc (doc);
|
||||
#endif // GST_DISABLE_REGISTRY
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -845,7 +845,7 @@ gst_plugin_load_thyself (xmlNodePtr parent)
|
|||
}
|
||||
GST_INFO (GST_CAT_PLUGIN_LOADING, "added %d features ", featurecount);
|
||||
}
|
||||
#endif // GST_DISABLE_REGISTRY
|
||||
#endif /* GST_DISABLE_REGISTRY */
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,15 +24,9 @@
|
|||
#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>
|
||||
|
||||
|
|
|
@ -987,7 +987,7 @@ end:
|
|||
return compatible;
|
||||
}
|
||||
|
||||
#if (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) )
|
||||
#ifndef GST_DISABLE_LOADSAVE_REGISTRY
|
||||
static xmlNodePtr
|
||||
gst_props_save_thyself_func (GstPropsEntry *entry, xmlNodePtr parent)
|
||||
{
|
||||
|
@ -1242,5 +1242,5 @@ gst_props_load_thyself (xmlNodePtr parent)
|
|||
|
||||
return props;
|
||||
}
|
||||
#endif /* (! (defined(GST_DISABLE_LOADSAVE) && defined(GST_DISABLE_REGISTRY)) ) */
|
||||
#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
|
||||
|
||||
|
|
|
@ -24,16 +24,9 @@
|
|||
#ifndef __GST_PROPS_H__
|
||||
#define __GST_PROPS_H__
|
||||
|
||||
#include <gst/gstconfig.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
|
||||
|
||||
|
||||
typedef struct _GstProps GstProps;
|
||||
|
||||
|
@ -95,7 +88,9 @@ gulong gst_props_get_fourcc_int (GstProps *props, const gchar *name);
|
|||
gboolean gst_props_get_boolean (GstProps *props, const gchar *name);
|
||||
const gchar* gst_props_get_string (GstProps *props, const gchar *name);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlNodePtr gst_props_save_thyself (GstProps *props, xmlNodePtr parent);
|
||||
GstProps* gst_props_load_thyself (xmlNodePtr parent);
|
||||
#endif
|
||||
|
||||
#endif /* __GST_PROPS_H__ */
|
||||
|
|
|
@ -1424,7 +1424,7 @@ GST_DEBUG(GST_CAT_SCHEDULING,"there are %d elements in this chain\n",chain->num_
|
|||
}
|
||||
} else {
|
||||
GST_INFO (GST_CAT_DATAFLOW,"NO ENABLED ELEMENTS IN CHAIN!!");
|
||||
//eos = TRUE;
|
||||
eos = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -124,16 +124,16 @@ gst_thread_class_init (GstThreadClass *klass)
|
|||
gobject_class->dispose = gst_thread_dispose;
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
gstobject_class->save_thyself = gst_thread_save_thyself;
|
||||
gstobject_class->restore_thyself = gst_thread_restore_thyself;
|
||||
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_thread_save_thyself);
|
||||
gstobject_class->restore_thyself = GST_DEBUG_FUNCPTR(gst_thread_restore_thyself);
|
||||
#endif
|
||||
|
||||
gstelement_class->change_state = gst_thread_change_state;
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_thread_change_state);
|
||||
|
||||
// gstbin_class->schedule = gst_thread_schedule_dummy;
|
||||
|
||||
gobject_class->set_property = gst_thread_set_property;
|
||||
gobject_class->get_property = gst_thread_get_property;
|
||||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_thread_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_thread_get_property);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -28,4 +28,6 @@
|
|||
#define GST_VERSION_MINOR @GST_VERSION_MINOR@
|
||||
#define GST_VERSION_MICRO @GST_VERSION_MICRO@
|
||||
|
||||
void gst_version (guint *major, guint *minor, guint *micro);
|
||||
|
||||
#endif /* __GST_H__ */
|
||||
|
|
11
gst/gstxml.h
11
gst/gstxml.h
|
@ -23,17 +23,10 @@
|
|||
#ifndef __GST_XML_H__
|
||||
#define __GST_XML_H__
|
||||
|
||||
#include <gst/gstconfig.h>
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
|
||||
#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
|
||||
|
||||
#include <gst/gstelement.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
113
gst/utils/gstbytestream.c
Normal file
113
gst/utils/gstbytestream.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
/* 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);
|
||||
}
|
56
gst/utils/gstbytestream.h
Normal file
56
gst/utils/gstbytestream.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* 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__ */
|
|
@ -402,7 +402,7 @@ gst_play_set_uri (GstPlay *play, const guchar *uri)
|
|||
}
|
||||
|
||||
if (priv->src == NULL) {
|
||||
priv->src = gst_elementfactory_make ("disksrc", "srcelement");
|
||||
priv->src = gst_elementfactory_make ("filesrc", "srcelement");
|
||||
}
|
||||
|
||||
priv->uri = g_strdup (uri);
|
||||
|
|
|
@ -25,7 +25,9 @@ main (int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlSaveFile ("gstmediaplay.gst", gst_xml_write (gst_play_get_pipeline (play->play)));
|
||||
#endif
|
||||
|
||||
gdk_threads_enter();
|
||||
gst_main();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
SUBDIRS = riff getbits putbits idct audio bytestream control
|
||||
|
||||
SUBDIRS = riff getbits putbits idct audio control
|
||||
|
||||
DIST_SUBDIRS = riff getbits putbits audio idct control
|
||||
DIST_SUBDIRS = riff getbits putbits audio idct bytestream control
|
||||
|
|
11
libs/bytestream/Makefile.am
Normal file
11
libs/bytestream/Makefile.am
Normal file
|
@ -0,0 +1,11 @@
|
|||
filterdir = $(libdir)/gst
|
||||
|
||||
filter_LTLIBRARIES = libgstbytestream.la libgstbstest.la
|
||||
|
||||
libgstbytestream_la_SOURCES = gstbytestream.c
|
||||
libgstbstest_la_SOURCES = gstbstest.c
|
||||
|
||||
libgstbytestreamincludedir = $(includedir)/gst/libs/bytestream
|
||||
libgstbytestreaminclude_HEADERS = gstbytestream.h
|
||||
|
||||
# CFLAGS += -O2 $(FOMIT_FRAME_POINTER) -funroll-all-loops -finline-functions -ffast-math
|
294
libs/bytestream/gstbstest.c
Normal file
294
libs/bytestream/gstbstest.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
/* 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
|
||||
};
|
||||
|
394
libs/bytestream/gstbytestream.c
Normal file
394
libs/bytestream/gstbytestream.c
Normal file
|
@ -0,0 +1,394 @@
|
|||
/* 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));
|
||||
}
|
||||
}
|
53
libs/bytestream/gstbytestream.h
Normal file
53
libs/bytestream/gstbytestream.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* 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__ */
|
|
@ -8,6 +8,8 @@ else
|
|||
GSTHTTPSRC=
|
||||
endif
|
||||
|
||||
#CFLAGS += -O2 -Wall -finstrument-functions -DGST_ENABLE_FUNC_INSTRUMENTATION
|
||||
|
||||
libgstelements_la_DEPENDENCIES = ../libgst.la
|
||||
libgstelements_la_SOURCES = \
|
||||
gstelements.c \
|
||||
|
@ -37,8 +39,10 @@ noinst_HEADERS = \
|
|||
gstfdsink.h \
|
||||
gstpipefilter.h \
|
||||
gsttee.h \
|
||||
gstaggregator.h
|
||||
CFLAGS += -O2 -Wall
|
||||
gstaggregator.h \
|
||||
gstsinesrc.h
|
||||
|
||||
CFLAGS += -O2 -Wall
|
||||
LDFLAGS += -lm
|
||||
|
||||
libgstelements_la_LIBADD = $(GHTTP_LIBS)
|
||||
|
|
|
@ -76,7 +76,8 @@ gst_aggregator_sched_get_type (void)
|
|||
static void gst_aggregator_class_init (GstAggregatorClass *klass);
|
||||
static void gst_aggregator_init (GstAggregator *aggregator);
|
||||
|
||||
static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp);
|
||||
static GstPad* gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *temp, const
|
||||
gchar *unused);
|
||||
|
||||
static void gst_aggregator_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
|
@ -150,7 +151,7 @@ gst_aggregator_init (GstAggregator *aggregator)
|
|||
}
|
||||
|
||||
static GstPad*
|
||||
gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
||||
gst_aggregator_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *sinkpad;
|
||||
|
|
|
@ -64,8 +64,8 @@ static void gst_disksrc_set_property (GObject *object, guint prop_id,
|
|||
static void gst_disksrc_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static GstBuffer * gst_disksrc_get (GstPad *pad);
|
||||
static GstBuffer * gst_disksrc_get_region (GstPad *pad,GstRegionType type,guint64 offset,guint64 len);
|
||||
static GstBuffer* gst_disksrc_get (GstPad *pad);
|
||||
static GstBufferPool* gst_disksrc_get_bufferpool (GstPad *pad);
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_disksrc_change_state (GstElement *element);
|
||||
|
@ -73,7 +73,7 @@ static GstElementStateReturn
|
|||
static gboolean gst_disksrc_open_file (GstDiskSrc *src);
|
||||
static void gst_disksrc_close_file (GstDiskSrc *src);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
static GstElementClass* parent_class = NULL;
|
||||
//static guint gst_disksrc_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
GType
|
||||
|
@ -133,8 +133,8 @@ gst_disksrc_init (GstDiskSrc *disksrc)
|
|||
// GST_FLAG_SET (disksrc, GST_SRC_);
|
||||
|
||||
disksrc->srcpad = gst_pad_new ("src", GST_PAD_SRC);
|
||||
gst_pad_set_get_function (disksrc->srcpad,gst_disksrc_get);
|
||||
gst_pad_set_getregion_function (disksrc->srcpad,gst_disksrc_get_region);
|
||||
gst_pad_set_get_function (disksrc->srcpad, gst_disksrc_get);
|
||||
gst_pad_set_bufferpool_function (disksrc->srcpad, gst_disksrc_get_bufferpool);
|
||||
gst_element_add_pad (GST_ELEMENT (disksrc), disksrc->srcpad);
|
||||
|
||||
disksrc->filename = NULL;
|
||||
|
@ -220,6 +220,56 @@ gst_disksrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
}
|
||||
}
|
||||
|
||||
static GstBuffer*
|
||||
gst_disksrc_buffer_new (GstBufferPool *pool, gint64 location, gint size, gpointer user_data)
|
||||
{
|
||||
GstDiskSrc *src;
|
||||
GstBuffer *buf;
|
||||
|
||||
src = GST_DISKSRC (user_data);
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
/* simply set the buffer to point to the correct region of the file */
|
||||
GST_BUFFER_DATA (buf) = src->map + location;
|
||||
GST_BUFFER_OFFSET (buf) = location;
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
|
||||
|
||||
if ((location + size) > src->size)
|
||||
GST_BUFFER_SIZE (buf) = src->size - location;
|
||||
else
|
||||
GST_BUFFER_SIZE (buf) = size;
|
||||
|
||||
GST_DEBUG (0,"map %p, offset %ld (%p), size %d\n", src->map, src->curoffset,
|
||||
src->map + src->curoffset, GST_BUFFER_SIZE (buf));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_disksrc_buffer_free (GstBuffer *buf)
|
||||
{
|
||||
// FIXME do something here
|
||||
}
|
||||
|
||||
static GstBufferPool*
|
||||
gst_disksrc_get_bufferpool (GstPad *pad)
|
||||
{
|
||||
GstDiskSrc *src;
|
||||
|
||||
src = GST_DISKSRC (gst_pad_get_parent (pad));
|
||||
|
||||
if (!src->bufferpool) {
|
||||
src->bufferpool = gst_buffer_pool_new ();
|
||||
gst_buffer_pool_set_buffer_new_function (src->bufferpool, gst_disksrc_buffer_new);
|
||||
gst_buffer_pool_set_buffer_free_function (src->bufferpool, gst_disksrc_buffer_free);
|
||||
gst_buffer_pool_set_user_data (src->bufferpool, src);
|
||||
}
|
||||
|
||||
return src->bufferpool;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_disksrc_get:
|
||||
* @pad: #GstPad to push a buffer from
|
||||
|
@ -246,28 +296,10 @@ gst_disksrc_get (GstPad *pad)
|
|||
return buf;
|
||||
}
|
||||
|
||||
/* create the buffer */
|
||||
// FIXME: should eventually use a bufferpool for this
|
||||
buf = gst_buffer_new ();
|
||||
|
||||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
/* simply set the buffer to point to the correct region of the file */
|
||||
GST_BUFFER_DATA (buf) = src->map + src->curoffset;
|
||||
GST_BUFFER_OFFSET (buf) = src->curoffset;
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
|
||||
|
||||
if ((src->curoffset + src->bytes_per_read) > src->size) {
|
||||
GST_BUFFER_SIZE (buf) = src->size - src->curoffset;
|
||||
// FIXME: set the buffer's EOF bit here
|
||||
} else
|
||||
GST_BUFFER_SIZE (buf) = src->bytes_per_read;
|
||||
|
||||
GST_DEBUG (0,"map %p, offset %ld (%p), size %d\n", src->map, src->curoffset,
|
||||
src->map + src->curoffset, GST_BUFFER_SIZE (buf));
|
||||
// FIXME use a bufferpool
|
||||
buf = gst_disksrc_buffer_new (NULL, src->curoffset, src->bytes_per_read, src);
|
||||
|
||||
//gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
|
||||
src->curoffset += GST_BUFFER_SIZE (buf);
|
||||
|
||||
if (src->new_seek) {
|
||||
|
@ -280,61 +312,6 @@ gst_disksrc_get (GstPad *pad)
|
|||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_disksrc_get_region:
|
||||
* @src: #GstSrc to push a buffer from
|
||||
* @offset: offset in file
|
||||
* @size: number of bytes
|
||||
*
|
||||
* Push a new buffer from the disksrc of given size at given offset.
|
||||
*/
|
||||
static GstBuffer *
|
||||
gst_disksrc_get_region (GstPad *pad, GstRegionType type,guint64 offset,guint64 len)
|
||||
{
|
||||
GstDiskSrc *src;
|
||||
GstBuffer *buf;
|
||||
|
||||
g_return_val_if_fail (pad != NULL, NULL);
|
||||
g_return_val_if_fail (type == GST_REGION_OFFSET_LEN, NULL);
|
||||
|
||||
src = GST_DISKSRC (gst_pad_get_parent (pad));
|
||||
|
||||
g_return_val_if_fail (GST_IS_DISKSRC (src), NULL);
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_DISKSRC_OPEN), NULL);
|
||||
|
||||
/* deal with EOF state */
|
||||
if (offset >= src->size) {
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
GST_DEBUG (0,"map offset %lld >= size %ld --> eos\n", offset, src->size);
|
||||
//FIXME
|
||||
buf = gst_buffer_new();
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_EOS);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* create the buffer */
|
||||
// FIXME: should eventually use a bufferpool for this
|
||||
buf = gst_buffer_new ();
|
||||
g_return_val_if_fail (buf != NULL, NULL);
|
||||
|
||||
/* simply set the buffer to point to the correct region of the file */
|
||||
GST_BUFFER_DATA (buf) = src->map + offset;
|
||||
GST_BUFFER_OFFSET (buf) = offset;
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
|
||||
|
||||
if ((offset + len) > src->size) {
|
||||
GST_BUFFER_SIZE (buf) = src->size - offset;
|
||||
// FIXME: set the buffer's EOF bit here
|
||||
} else
|
||||
GST_BUFFER_SIZE (buf) = len;
|
||||
|
||||
GST_DEBUG (0,"map %p, offset %lld, size %d\n", src->map, offset, GST_BUFFER_SIZE (buf));
|
||||
|
||||
/* we're done, return the buffer off now */
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/* open the file and mmap it, necessary to go to READY state */
|
||||
static gboolean
|
||||
gst_disksrc_open_file (GstDiskSrc *src)
|
||||
|
|
|
@ -64,6 +64,7 @@ struct _GstDiskSrc {
|
|||
gchar *filename;
|
||||
/* fd */
|
||||
gint fd;
|
||||
GstBufferPool *bufferpool;
|
||||
|
||||
/* mapping parameters */
|
||||
gulong size; /* how long is the file? */
|
||||
|
|
|
@ -45,6 +45,7 @@ enum {
|
|||
ARG_0,
|
||||
ARG_NUM_SINKS,
|
||||
ARG_SILENT,
|
||||
ARG_DUMP,
|
||||
};
|
||||
|
||||
GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
|
||||
|
@ -58,7 +59,8 @@ GST_PADTEMPLATE_FACTORY (fakesink_sink_factory,
|
|||
static void gst_fakesink_class_init (GstFakeSinkClass *klass);
|
||||
static void gst_fakesink_init (GstFakeSink *fakesink);
|
||||
|
||||
static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ);
|
||||
static GstPad* gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const
|
||||
gchar *unused);
|
||||
|
||||
static void gst_fakesink_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
|
@ -66,7 +68,6 @@ static void gst_fakesink_get_property (GObject *object, guint prop_id,
|
|||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static void gst_fakesink_chain (GstPad *pad, GstBuffer *buf);
|
||||
static gboolean gst_fakesink_event (GstPad *pad, GstEventType event, guint64 timestamp, guint32 data);
|
||||
|
||||
static GstElementClass *parent_class = NULL;
|
||||
static guint gst_fakesink_signals[LAST_SIGNAL] = { 0 };
|
||||
|
@ -109,6 +110,9 @@ gst_fakesink_class_init (GstFakeSinkClass *klass)
|
|||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SILENT,
|
||||
g_param_spec_boolean ("silent", "silent", "silent",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_param_spec_boolean ("dump", "dump", "dump",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
gst_fakesink_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
|
@ -129,15 +133,15 @@ gst_fakesink_init (GstFakeSink *fakesink)
|
|||
pad = gst_pad_new ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (fakesink), pad);
|
||||
gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_chain));
|
||||
gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_fakesink_event));
|
||||
|
||||
fakesink->sinkpads = g_slist_prepend (NULL, pad);
|
||||
fakesink->numsinkpads = 1;
|
||||
fakesink->silent = FALSE;
|
||||
fakesink->dump = FALSE;
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
||||
gst_fakesink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *sinkpad;
|
||||
|
@ -175,6 +179,9 @@ gst_fakesink_set_property (GObject *object, guint prop_id, const GValue *value,
|
|||
case ARG_SILENT:
|
||||
sink->silent = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
sink->dump = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -197,6 +204,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
|||
case ARG_SILENT:
|
||||
g_value_set_boolean (value, sink->silent);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
g_value_set_boolean (value, sink->dump);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -206,9 +216,9 @@ gst_fakesink_get_property (GObject *object, guint prop_id, GValue *value, GParam
|
|||
/**
|
||||
* gst_fakesink_chain:
|
||||
* @pad: the pad this faksink is connected to
|
||||
* @buf: the buffer that has to be absorbed
|
||||
* @buffer: the buffer or event that has to be absorbed
|
||||
*
|
||||
* take the buffer from the pad and unref it without doing
|
||||
* Take the buffer or event from the pad and unref it without doing
|
||||
* anything with it.
|
||||
*/
|
||||
static void
|
||||
|
@ -221,12 +231,33 @@ gst_fakesink_chain (GstPad *pad, GstBuffer *buf)
|
|||
g_return_if_fail (buf != NULL);
|
||||
|
||||
fakesink = GST_FAKESINK (gst_pad_get_parent (pad));
|
||||
|
||||
if (GST_IS_EVENT(buf)) {
|
||||
GstEvent *event = GST_EVENT (buf);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
g_print("fakesink: have EOS event!\n");
|
||||
gst_element_set_state (GST_ELEMENT (fakesink), GST_STATE_PAUSED);
|
||||
break;
|
||||
default:
|
||||
g_print("fakesink: have unhandled event!\n");
|
||||
break;
|
||||
}
|
||||
gst_event_free (event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fakesink->silent)
|
||||
g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) \n",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
|
||||
g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0,
|
||||
buf);
|
||||
g_print("fakesink: chain ******* (%s:%s)< (%d bytes, %lld) %p\n",
|
||||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf), buf);
|
||||
|
||||
g_signal_emit (G_OBJECT (fakesink), gst_fakesink_signals[SIGNAL_HANDOFF], 0, buf, pad);
|
||||
|
||||
if (fakesink->dump)
|
||||
{
|
||||
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
}
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
@ -238,14 +269,3 @@ gst_fakesink_factory_init (GstElementFactory *factory)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_fakesink_event (GstPad *pad, GstEventType event, guint64 timestamp, guint32 data)
|
||||
{
|
||||
GST_DEBUG (GST_CAT_EVENT, "fakesink has event %d on pad %s:%s\n",event,GST_DEBUG_PAD_NAME(pad));
|
||||
if (event == GST_EVENT_EOS) {
|
||||
GST_DEBUG(GST_CAT_EVENT, "have EOS\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ struct _GstFakeSink {
|
|||
GSList *sinkpads;
|
||||
gint numsinkpads;
|
||||
gboolean silent;
|
||||
gboolean dump;
|
||||
};
|
||||
|
||||
struct _GstFakeSinkClass {
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gstfakesrc.h>
|
||||
|
||||
|
||||
|
@ -47,10 +50,17 @@ enum {
|
|||
ARG_NUM_SOURCES,
|
||||
ARG_LOOP_BASED,
|
||||
ARG_OUTPUT,
|
||||
ARG_DATA,
|
||||
ARG_SIZETYPE,
|
||||
ARG_SIZEMIN,
|
||||
ARG_SIZEMAX,
|
||||
ARG_FILLTYPE,
|
||||
ARG_PATTERN,
|
||||
ARG_NUM_BUFFERS,
|
||||
ARG_EOS,
|
||||
ARG_SILENT
|
||||
ARG_SILENT,
|
||||
ARG_DUMP,
|
||||
ARG_PARENTSIZE
|
||||
};
|
||||
|
||||
GST_PADTEMPLATE_FACTORY (fakesrc_src_factory,
|
||||
|
@ -82,12 +92,69 @@ gst_fakesrc_output_get_type (void)
|
|||
return fakesrc_output_type;
|
||||
}
|
||||
|
||||
#define GST_TYPE_FAKESRC_DATA (gst_fakesrc_data_get_type())
|
||||
static GType
|
||||
gst_fakesrc_data_get_type (void)
|
||||
{
|
||||
static GType fakesrc_data_type = 0;
|
||||
static GEnumValue fakesrc_data[] = {
|
||||
{ FAKESRC_DATA_ALLOCATE, "2", "Allocate data"},
|
||||
{ FAKESRC_DATA_SUBBUFFER, "3", "Subbuffer data"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_data_type) {
|
||||
fakesrc_data_type = g_enum_register_static ("GstFakeSrcData", fakesrc_data);
|
||||
}
|
||||
return fakesrc_data_type;
|
||||
}
|
||||
|
||||
#define GST_TYPE_FAKESRC_SIZETYPE (gst_fakesrc_sizetype_get_type())
|
||||
static GType
|
||||
gst_fakesrc_sizetype_get_type (void)
|
||||
{
|
||||
static GType fakesrc_sizetype_type = 0;
|
||||
static GEnumValue fakesrc_sizetype[] = {
|
||||
{ FAKESRC_SIZETYPE_NULL, "1", "Send empty buffers"},
|
||||
{ FAKESRC_SIZETYPE_FIXED, "2", "Fixed size buffers (sizemax sized)"},
|
||||
{ FAKESRC_SIZETYPE_RANDOM, "3", "Random sized buffers (sizemin <= size <= sizemax)"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_sizetype_type) {
|
||||
fakesrc_sizetype_type = g_enum_register_static ("GstFakeSrcSizeType", fakesrc_sizetype);
|
||||
}
|
||||
return fakesrc_sizetype_type;
|
||||
}
|
||||
|
||||
#define GST_TYPE_FAKESRC_FILLTYPE (gst_fakesrc_filltype_get_type())
|
||||
static GType
|
||||
gst_fakesrc_filltype_get_type (void)
|
||||
{
|
||||
static GType fakesrc_filltype_type = 0;
|
||||
static GEnumValue fakesrc_filltype[] = {
|
||||
{ FAKESRC_FILLTYPE_NOTHING, "1", "Leave data as malloced"},
|
||||
{ FAKESRC_FILLTYPE_NULL, "2", "Fill buffers with zeros"},
|
||||
{ FAKESRC_FILLTYPE_RANDOM, "3", "Fill buffers with random crap"},
|
||||
{ FAKESRC_FILLTYPE_PATTERN, "4", "Fill buffers with pattern 0x00 -> 0xff"},
|
||||
{ FAKESRC_FILLTYPE_PATTERN_CONT, "5", "Fill buffers with pattern 0x00 -> 0xff that spans buffers"},
|
||||
{0, NULL, NULL},
|
||||
};
|
||||
if (!fakesrc_filltype_type) {
|
||||
fakesrc_filltype_type = g_enum_register_static ("GstFakeSrcFillType", fakesrc_filltype);
|
||||
}
|
||||
return fakesrc_filltype_type;
|
||||
}
|
||||
|
||||
static void gst_fakesrc_class_init (GstFakeSrcClass *klass);
|
||||
static void gst_fakesrc_init (GstFakeSrc *fakesrc);
|
||||
|
||||
static GstPad* gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ);
|
||||
static void gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesrc_update_functions (GstFakeSrc *src);
|
||||
static void gst_fakesrc_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
static void gst_fakesrc_get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec);
|
||||
|
||||
static GstElementStateReturn gst_fakesrc_change_state (GstElement *element);
|
||||
|
||||
static GstBuffer* gst_fakesrc_get (GstPad *pad);
|
||||
static void gst_fakesrc_loop (GstElement *element);
|
||||
|
@ -137,6 +204,24 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
|
|||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_OUTPUT,
|
||||
g_param_spec_enum("output","output","output",
|
||||
GST_TYPE_FAKESRC_OUTPUT,FAKESRC_FIRST_LAST_LOOP,G_PARAM_READWRITE)); // CHECKME!
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DATA,
|
||||
g_param_spec_enum ("data", "data", "data",
|
||||
GST_TYPE_FAKESRC_DATA, FAKESRC_DATA_ALLOCATE, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZETYPE,
|
||||
g_param_spec_enum ("sizetype", "sizetype", "sizetype",
|
||||
GST_TYPE_FAKESRC_SIZETYPE, FAKESRC_SIZETYPE_NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMIN,
|
||||
g_param_spec_int ("sizemin","sizemin","sizemin",
|
||||
0, G_MAXINT, 0, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SIZEMAX,
|
||||
g_param_spec_int ("sizemax","sizemax","sizemax",
|
||||
0, G_MAXINT, 4096, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PARENTSIZE,
|
||||
g_param_spec_int ("parentsize","parentsize","parentsize",
|
||||
0, G_MAXINT, 4096 * 10, G_PARAM_READWRITE));
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILLTYPE,
|
||||
g_param_spec_enum ("filltype", "filltype", "filltype",
|
||||
GST_TYPE_FAKESRC_FILLTYPE, FAKESRC_FILLTYPE_NULL, G_PARAM_READWRITE));
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_PATTERN,
|
||||
g_param_spec_string("pattern","pattern","pattern",
|
||||
NULL, G_PARAM_READWRITE)); // CHECKME
|
||||
|
@ -149,6 +234,9 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
|
|||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_SILENT,
|
||||
g_param_spec_boolean("silent","silent","silent",
|
||||
FALSE, G_PARAM_READWRITE)); // CHECKME
|
||||
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DUMP,
|
||||
g_param_spec_boolean ("dump","dump","dump",
|
||||
FALSE, G_PARAM_READWRITE));
|
||||
|
||||
gst_fakesrc_signals[SIGNAL_HANDOFF] =
|
||||
g_signal_new ("handoff", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
|
||||
|
@ -159,7 +247,8 @@ gst_fakesrc_class_init (GstFakeSrcClass *klass)
|
|||
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_fakesrc_set_property);
|
||||
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_fakesrc_get_property);
|
||||
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
|
||||
gstelement_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_fakesrc_request_new_pad);
|
||||
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_fakesrc_change_state);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -176,17 +265,21 @@ gst_fakesrc_init (GstFakeSrc *fakesrc)
|
|||
fakesrc->srcpads = g_slist_append (NULL, pad);
|
||||
|
||||
fakesrc->loop_based = FALSE;
|
||||
|
||||
if (fakesrc->loop_based)
|
||||
gst_element_set_loop_function (GST_ELEMENT (fakesrc), GST_DEBUG_FUNCPTR (gst_fakesrc_loop));
|
||||
else
|
||||
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
|
||||
gst_fakesrc_update_functions (fakesrc);
|
||||
|
||||
fakesrc->num_buffers = -1;
|
||||
fakesrc->buffer_count = 0;
|
||||
fakesrc->silent = FALSE;
|
||||
// we're ready right away, since we don't have any args...
|
||||
// gst_element_set_state(GST_ELEMENT(fakesrc),GST_STATE_READY);
|
||||
fakesrc->dump = FALSE;
|
||||
fakesrc->pattern_byte = 0x00;
|
||||
fakesrc->need_flush = FALSE;
|
||||
fakesrc->data = FAKESRC_DATA_ALLOCATE;
|
||||
fakesrc->sizetype = FAKESRC_SIZETYPE_NULL;
|
||||
fakesrc->filltype = FAKESRC_FILLTYPE_NOTHING;
|
||||
fakesrc->sizemin = 0;
|
||||
fakesrc->sizemax = 4096;
|
||||
fakesrc->parent = NULL;
|
||||
fakesrc->parentsize = 4096 * 10;
|
||||
}
|
||||
|
||||
static GstPad*
|
||||
|
@ -216,6 +309,34 @@ gst_fakesrc_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
|||
return srcpad;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_fakesrc_event_handler (GstPad *pad, GstEvent *event)
|
||||
{
|
||||
GstFakeSrc *src;
|
||||
|
||||
src = GST_FAKESRC (gst_pad_get_parent (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
g_print("fakesrc: have seek event\n");
|
||||
src->buffer_count = GST_EVENT_SEEK_OFFSET (event);
|
||||
if (!GST_EVENT_SEEK_FLUSH (event)) {
|
||||
gst_event_free (event);
|
||||
break;
|
||||
}
|
||||
// else we do a flush too
|
||||
case GST_EVENT_FLUSH:
|
||||
g_print("fakesrc: have flush event\n");
|
||||
src->need_flush = TRUE;
|
||||
break;
|
||||
default:
|
||||
g_print("fakesrc: have unhandled event\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_update_functions (GstFakeSrc *src)
|
||||
{
|
||||
|
@ -238,10 +359,25 @@ gst_fakesrc_update_functions (GstFakeSrc *src)
|
|||
else {
|
||||
gst_pad_set_get_function (pad, GST_DEBUG_FUNCPTR (gst_fakesrc_get));
|
||||
}
|
||||
|
||||
gst_pad_set_event_function (pad, gst_fakesrc_event_handler);
|
||||
pads = g_slist_next (pads);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_alloc_parent (GstFakeSrc *src)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_DATA (buf) = g_malloc (src->parentsize);
|
||||
GST_BUFFER_SIZE (buf) = src->parentsize;
|
||||
|
||||
src->parent = buf;
|
||||
src->parentoffset = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
|
@ -257,6 +393,37 @@ gst_fakesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
break;
|
||||
case ARG_OUTPUT:
|
||||
break;
|
||||
case ARG_DATA:
|
||||
src->data = g_value_get_int (value);
|
||||
switch (src->data) {
|
||||
case FAKESRC_DATA_ALLOCATE:
|
||||
if (src->parent) {
|
||||
gst_buffer_unref (src->parent);
|
||||
src->parent = NULL;
|
||||
}
|
||||
break;
|
||||
case FAKESRC_DATA_SUBBUFFER:
|
||||
if (!src->parent)
|
||||
gst_fakesrc_alloc_parent (src);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ARG_SIZETYPE:
|
||||
src->sizetype = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_SIZEMIN:
|
||||
src->sizemin = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_SIZEMAX:
|
||||
src->sizemax = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_PARENTSIZE:
|
||||
src->parentsize = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_FILLTYPE:
|
||||
src->filltype = g_value_get_int (value);
|
||||
break;
|
||||
case ARG_PATTERN:
|
||||
break;
|
||||
case ARG_NUM_BUFFERS:
|
||||
|
@ -269,6 +436,9 @@ GST_INFO (0, "will EOS on next buffer");
|
|||
case ARG_SILENT:
|
||||
src->silent = g_value_get_boolean (value);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
src->dump = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -294,6 +464,24 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
case ARG_OUTPUT:
|
||||
g_value_set_int (value, src->output);
|
||||
break;
|
||||
case ARG_DATA:
|
||||
g_value_set_int (value, src->data);
|
||||
break;
|
||||
case ARG_SIZETYPE:
|
||||
g_value_set_int (value, src->sizetype);
|
||||
break;
|
||||
case ARG_SIZEMIN:
|
||||
g_value_set_int (value, src->sizemin);
|
||||
break;
|
||||
case ARG_SIZEMAX:
|
||||
g_value_set_int (value, src->sizemax);
|
||||
break;
|
||||
case ARG_PARENTSIZE:
|
||||
g_value_set_int (value, src->parentsize);
|
||||
break;
|
||||
case ARG_FILLTYPE:
|
||||
g_value_set_int (value, src->filltype);
|
||||
break;
|
||||
case ARG_PATTERN:
|
||||
g_value_set_string (value, src->pattern);
|
||||
break;
|
||||
|
@ -306,21 +494,150 @@ gst_fakesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
case ARG_SILENT:
|
||||
g_value_set_boolean (value, src->silent);
|
||||
break;
|
||||
case ARG_DUMP:
|
||||
g_value_set_boolean (value, src->dump);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_fakesrc_prepare_buffer (GstFakeSrc *src, GstBuffer *buf)
|
||||
{
|
||||
if (GST_BUFFER_SIZE (buf) == 0)
|
||||
return;
|
||||
|
||||
switch (src->filltype) {
|
||||
case FAKESRC_FILLTYPE_NULL:
|
||||
memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf));
|
||||
break;
|
||||
case FAKESRC_FILLTYPE_RANDOM:
|
||||
{
|
||||
gint i;
|
||||
guint8 *ptr = GST_BUFFER_DATA (buf);
|
||||
|
||||
for (i = GST_BUFFER_SIZE (buf); i; i--) {
|
||||
*ptr++ = (gint8)((255.0)*rand()/(RAND_MAX));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FAKESRC_FILLTYPE_PATTERN:
|
||||
src->pattern_byte = 0x00;
|
||||
case FAKESRC_FILLTYPE_PATTERN_CONT:
|
||||
{
|
||||
gint i;
|
||||
guint8 *ptr = GST_BUFFER_DATA (buf);
|
||||
|
||||
for (i = GST_BUFFER_SIZE (buf); i; i--) {
|
||||
*ptr++ = src->pattern_byte++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FAKESRC_FILLTYPE_NOTHING:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GstBuffer*
|
||||
gst_fakesrc_alloc_buffer (GstFakeSrc *src, guint size)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
|
||||
buf = gst_buffer_new ();
|
||||
GST_BUFFER_SIZE(buf) = size;
|
||||
|
||||
if (size != 0) {
|
||||
switch (src->filltype) {
|
||||
case FAKESRC_FILLTYPE_NOTHING:
|
||||
GST_BUFFER_DATA(buf) = g_malloc (size);
|
||||
break;
|
||||
case FAKESRC_FILLTYPE_NULL:
|
||||
GST_BUFFER_DATA(buf) = g_malloc0 (size);
|
||||
break;
|
||||
case FAKESRC_FILLTYPE_RANDOM:
|
||||
case FAKESRC_FILLTYPE_PATTERN:
|
||||
case FAKESRC_FILLTYPE_PATTERN_CONT:
|
||||
default:
|
||||
GST_BUFFER_DATA(buf) = g_malloc (size);
|
||||
gst_fakesrc_prepare_buffer (src, buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static guint
|
||||
gst_fakesrc_get_size (GstFakeSrc *src)
|
||||
{
|
||||
guint size;
|
||||
|
||||
switch (src->sizetype) {
|
||||
case FAKESRC_SIZETYPE_FIXED:
|
||||
size = src->sizemax;
|
||||
break;
|
||||
case FAKESRC_SIZETYPE_RANDOM:
|
||||
size = src->sizemin + (guint8)(((gfloat)src->sizemax)*rand()/(RAND_MAX + (gfloat)src->sizemin));
|
||||
break;
|
||||
case FAKESRC_SIZETYPE_NULL:
|
||||
default:
|
||||
size = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_fakesrc_create_buffer (GstFakeSrc *src)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
guint size;
|
||||
gboolean dump = src->dump;
|
||||
|
||||
size = gst_fakesrc_get_size (src);
|
||||
if (size == 0)
|
||||
return gst_buffer_new();
|
||||
|
||||
switch (src->data) {
|
||||
case FAKESRC_DATA_ALLOCATE:
|
||||
buf = gst_fakesrc_alloc_buffer (src, size);
|
||||
break;
|
||||
case FAKESRC_DATA_SUBBUFFER:
|
||||
// see if we have a parent to subbuffer
|
||||
if (!src->parent) {
|
||||
gst_fakesrc_alloc_parent (src);
|
||||
g_assert (src->parent);
|
||||
}
|
||||
// see if it's large enough
|
||||
if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) {
|
||||
buf = gst_buffer_create_sub (src->parent, src->parentoffset, size);
|
||||
src->parentoffset += size;
|
||||
}
|
||||
else {
|
||||
// the parent is useless now
|
||||
gst_buffer_unref (src->parent);
|
||||
src->parent = NULL;
|
||||
// try again (this will allocate a new parent)
|
||||
return gst_fakesrc_create_buffer (src);
|
||||
}
|
||||
gst_fakesrc_prepare_buffer (src, buf);
|
||||
break;
|
||||
default:
|
||||
g_warning ("fakesrc: dunno how to allocate buffers !");
|
||||
buf = gst_buffer_new();
|
||||
break;
|
||||
}
|
||||
if (dump) {
|
||||
gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_fakesrc_get:
|
||||
* @src: the faksesrc to get
|
||||
*
|
||||
* generate an empty buffer and return it
|
||||
*
|
||||
* Returns: a new empty buffer
|
||||
*/
|
||||
static GstBuffer *
|
||||
gst_fakesrc_get(GstPad *pad)
|
||||
{
|
||||
|
@ -333,9 +650,16 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
g_return_val_if_fail (GST_IS_FAKESRC (src), NULL);
|
||||
|
||||
if (src->need_flush) {
|
||||
src->need_flush = FALSE;
|
||||
g_print("fakesrc: sending FLUSH\n");
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_FLUSH));
|
||||
}
|
||||
|
||||
if (src->num_buffers == 0) {
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
return NULL;
|
||||
g_print("fakesrc: sending EOS\n");
|
||||
gst_element_set_state (GST_ELEMENT (src), GST_STATE_PAUSED);
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
else {
|
||||
if (src->num_buffers > 0)
|
||||
|
@ -344,11 +668,11 @@ gst_fakesrc_get(GstPad *pad)
|
|||
|
||||
if (src->eos) {
|
||||
GST_INFO (0, "fakesrc is setting eos on pad");
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
return NULL;
|
||||
g_print("fakesrc: sending EOS\n");
|
||||
return GST_BUFFER(gst_event_new (GST_EVENT_EOS));
|
||||
}
|
||||
|
||||
buf = gst_buffer_new();
|
||||
buf = gst_fakesrc_create_buffer (src);
|
||||
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
|
||||
|
||||
if (!src->silent)
|
||||
|
@ -356,7 +680,7 @@ gst_fakesrc_get(GstPad *pad)
|
|||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
buf);
|
||||
buf, pad);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -387,21 +711,20 @@ gst_fakesrc_loop(GstElement *element)
|
|||
GstBuffer *buf;
|
||||
|
||||
if (src->num_buffers == 0) {
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
return;
|
||||
src->eos = TRUE;
|
||||
}
|
||||
else {
|
||||
if (src->num_buffers > 0)
|
||||
src->num_buffers--;
|
||||
if (src->num_buffers > 0)
|
||||
src->num_buffers--;
|
||||
}
|
||||
|
||||
if (src->eos) {
|
||||
GST_INFO (0, "fakesrc is setting eos on pad");
|
||||
gst_pad_event (pad, GST_EVENT_EOS, 0LL, 0);
|
||||
return;
|
||||
gst_pad_push(pad, GST_BUFFER(gst_event_new (GST_EVENT_EOS)));
|
||||
return;
|
||||
}
|
||||
|
||||
buf = gst_buffer_new();
|
||||
buf = gst_fakesrc_create_buffer (src);
|
||||
GST_BUFFER_TIMESTAMP (buf) = src->buffer_count++;
|
||||
|
||||
if (!src->silent)
|
||||
|
@ -409,7 +732,7 @@ gst_fakesrc_loop(GstElement *element)
|
|||
GST_DEBUG_PAD_NAME (pad), GST_BUFFER_SIZE (buf), GST_BUFFER_TIMESTAMP (buf));
|
||||
|
||||
g_signal_emit (G_OBJECT (src), gst_fakesrc_signals[SIGNAL_HANDOFF], 0,
|
||||
buf);
|
||||
buf, pad);
|
||||
gst_pad_push (pad, buf);
|
||||
|
||||
pads = g_slist_next (pads);
|
||||
|
@ -417,6 +740,31 @@ gst_fakesrc_loop(GstElement *element)
|
|||
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
gst_fakesrc_change_state (GstElement *element)
|
||||
{
|
||||
GstFakeSrc *fakesrc;
|
||||
|
||||
g_return_val_if_fail (GST_IS_FAKESRC (element), GST_STATE_FAILURE);
|
||||
|
||||
fakesrc = GST_FAKESRC (element);
|
||||
|
||||
if (GST_STATE_PENDING (element) == GST_STATE_READY) {
|
||||
fakesrc->buffer_count = 0;
|
||||
fakesrc->pattern_byte = 0x00;
|
||||
fakesrc->need_flush = FALSE;
|
||||
if (fakesrc->parent) {
|
||||
gst_buffer_unref (fakesrc->parent);
|
||||
fakesrc->parent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
||||
return GST_STATE_SUCCESS;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_fakesrc_factory_init (GstElementFactory *factory)
|
||||
{
|
||||
|
|
|
@ -47,6 +47,25 @@ typedef enum {
|
|||
FAKESRC_GET_ALWAYS_SUCEEDS,
|
||||
} GstFakeSrcOutputType;
|
||||
|
||||
typedef enum {
|
||||
FAKESRC_DATA_ALLOCATE = 1,
|
||||
FAKESRC_DATA_SUBBUFFER,
|
||||
} GstFakeSrcDataType;
|
||||
|
||||
typedef enum {
|
||||
FAKESRC_SIZETYPE_NULL = 1,
|
||||
FAKESRC_SIZETYPE_FIXED,
|
||||
FAKESRC_SIZETYPE_RANDOM
|
||||
} GstFakeSrcSizeType;
|
||||
|
||||
typedef enum {
|
||||
FAKESRC_FILLTYPE_NOTHING = 1,
|
||||
FAKESRC_FILLTYPE_NULL,
|
||||
FAKESRC_FILLTYPE_RANDOM,
|
||||
FAKESRC_FILLTYPE_PATTERN,
|
||||
FAKESRC_FILLTYPE_PATTERN_CONT
|
||||
} GstFakeSrcFillType;
|
||||
|
||||
#define GST_TYPE_FAKESRC \
|
||||
(gst_fakesrc_get_type())
|
||||
#define GST_FAKESRC(obj) \
|
||||
|
@ -64,16 +83,29 @@ typedef struct _GstFakeSrcClass GstFakeSrcClass;
|
|||
struct _GstFakeSrc {
|
||||
GstElement element;
|
||||
|
||||
gboolean loop_based;
|
||||
gboolean eos;
|
||||
gint numsrcpads;
|
||||
GSList *srcpads;
|
||||
gboolean loop_based;
|
||||
gboolean eos;
|
||||
gint numsrcpads;
|
||||
GSList *srcpads;
|
||||
|
||||
GstFakeSrcOutputType output;
|
||||
gchar *pattern;
|
||||
GList *patternlist;
|
||||
gint num_buffers;
|
||||
guint64 buffer_count;
|
||||
gboolean silent;
|
||||
GstFakeSrcDataType data;
|
||||
GstFakeSrcSizeType sizetype;
|
||||
GstFakeSrcFillType filltype;
|
||||
|
||||
guint sizemin;
|
||||
guint sizemax;
|
||||
GstBuffer *parent;
|
||||
guint parentsize;
|
||||
guint parentoffset;
|
||||
guint8 pattern_byte;
|
||||
gchar *pattern;
|
||||
GList *patternlist;
|
||||
gint num_buffers;
|
||||
guint64 buffer_count;
|
||||
gboolean silent;
|
||||
gboolean dump;
|
||||
gboolean need_flush;
|
||||
};
|
||||
|
||||
struct _GstFakeSrcClass {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -74,6 +75,9 @@ GstElementDetails gst_filesrc_details = {
|
|||
"(C) 1999",
|
||||
};
|
||||
|
||||
//#define fs_print(format,args...) g_print(format, ## args)
|
||||
#define fs_print(format,args...)
|
||||
|
||||
|
||||
#define GST_TYPE_FILESRC \
|
||||
(gst_filesrc_get_type())
|
||||
|
@ -110,10 +114,12 @@ struct _GstFileSrc {
|
|||
gboolean touch; // whether to touch every page
|
||||
|
||||
GstBuffer *mapbuf;
|
||||
off_t mapsize;
|
||||
size_t mapsize;
|
||||
|
||||
GTree *map_regions;
|
||||
GMutex *map_regions_lock;
|
||||
|
||||
gboolean seek_happened;
|
||||
};
|
||||
|
||||
struct _GstFileSrcClass {
|
||||
|
@ -135,6 +141,7 @@ enum {
|
|||
ARG_BLOCKSIZE,
|
||||
ARG_OFFSET,
|
||||
ARG_MAPSIZE,
|
||||
ARG_TOUCH,
|
||||
};
|
||||
|
||||
|
||||
|
@ -203,6 +210,9 @@ gst_filesrc_class_init (GstFileSrcClass *klass)
|
|||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_MAPSIZE,
|
||||
g_param_spec_ulong("mmapsize","mmap() Block Size","Size in bytes of mmap()d regions",
|
||||
0,G_MAXULONG,4*1048576,G_PARAM_READWRITE));
|
||||
g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_TOUCH,
|
||||
g_param_spec_boolean("touch","Touch read data","Touch data to force disk read before push()",
|
||||
TRUE,G_PARAM_READWRITE));
|
||||
|
||||
gobject_class->set_property = gst_filesrc_set_property;
|
||||
gobject_class->get_property = gst_filesrc_get_property;
|
||||
|
@ -246,6 +256,8 @@ gst_filesrc_init (GstFileSrc *src)
|
|||
|
||||
src->map_regions = g_tree_new(gst_filesrc_bufcmp);
|
||||
src->map_regions_lock = g_mutex_new();
|
||||
|
||||
src->seek_happened = FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -286,6 +298,9 @@ gst_filesrc_set_property (GObject *object, guint prop_id, const GValue *value, G
|
|||
else
|
||||
GST_INFO(0, "invalid mapsize, must a multiple of pagesize, which is %d\n",src->pagesize);
|
||||
break;
|
||||
case ARG_TOUCH:
|
||||
src->touch = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -320,6 +335,9 @@ gst_filesrc_get_property (GObject *object, guint prop_id, GValue *value, GParamS
|
|||
case ARG_MAPSIZE:
|
||||
g_value_set_ulong (value, src->mapsize);
|
||||
break;
|
||||
case ARG_TOUCH:
|
||||
g_value_set_boolean (value, src->touch);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -331,7 +349,7 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
|
|||
{
|
||||
GstFileSrc *src = GST_FILESRC(GST_BUFFER_POOL_PRIVATE(buf));
|
||||
|
||||
// fprintf(stderr,"freeing mmap()d buffer at %d+%d\n",GST_BUFFER_OFFSET(buf),GST_BUFFER_SIZE(buf));
|
||||
fs_print ("freeing mmap()d buffer at %d+%d\n",GST_BUFFER_OFFSET(buf),GST_BUFFER_SIZE(buf));
|
||||
|
||||
// remove the buffer from the list of available mmap'd regions
|
||||
g_mutex_lock(src->map_regions_lock);
|
||||
|
@ -347,21 +365,24 @@ gst_filesrc_free_parent_mmap (GstBuffer *buf)
|
|||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_filesrc_map_region (GstFileSrc *src, off_t offset, off_t size)
|
||||
gst_filesrc_map_region (GstFileSrc *src, off_t offset, size_t size)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
gint retval;
|
||||
|
||||
// fprintf(stderr,"mapping region %d+%d from file into memory\n",offset,size);
|
||||
g_return_val_if_fail (offset >= 0, NULL);
|
||||
|
||||
fs_print ("mapping region %08lx+%08lx from file into memory\n",offset,size);
|
||||
|
||||
// time to allocate a new mapbuf
|
||||
buf = gst_buffer_new();
|
||||
// mmap() the data into this new buffer
|
||||
GST_BUFFER_DATA(buf) = mmap (NULL, size, PROT_READ, MAP_SHARED, src->fd, offset);
|
||||
if (GST_BUFFER_DATA(buf) == NULL) {
|
||||
fprintf(stderr, "ERROR: gstfilesrc couldn't map file!\n");
|
||||
} else if (GST_BUFFER_DATA(buf) == (void *)-1) {
|
||||
perror("gstfilesrc:mmap()");
|
||||
fprintf (stderr, "ERROR: gstfilesrc couldn't map file!\n");
|
||||
} else if (GST_BUFFER_DATA(buf) == MAP_FAILED) {
|
||||
g_error ("gstfilesrc mmap(0x%x, %d, 0x%llx) : %s",
|
||||
size, src->fd, offset, sys_errlist[errno]);
|
||||
}
|
||||
// madvise to tell the kernel what to do with it
|
||||
retval = madvise(GST_BUFFER_DATA(buf),GST_BUFFER_SIZE(buf),MADV_SEQUENTIAL);
|
||||
|
@ -382,20 +403,27 @@ gst_filesrc_map_region (GstFileSrc *src, off_t offset, off_t size)
|
|||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, off_t size)
|
||||
gst_filesrc_map_small_region (GstFileSrc *src, off_t offset, size_t size)
|
||||
{
|
||||
int mod, mapbase, mapsize;
|
||||
size_t mapsize;
|
||||
off_t mod, mapbase;
|
||||
GstBuffer *map;
|
||||
|
||||
// printf("attempting to map a small buffer at %d+%d\n",offset,size);
|
||||
|
||||
// if the offset starts at a non-page boundary, we have to special case
|
||||
if ((mod = offset % src->pagesize)) {
|
||||
GstBuffer *ret;
|
||||
|
||||
mapbase = offset - mod;
|
||||
mapsize = ((size + mod + src->pagesize - 1) / src->pagesize) * src->pagesize;
|
||||
// printf("not on page boundaries, resizing map to %d+%d\n",mapbase,mapsize);
|
||||
map = gst_filesrc_map_region(src, mapbase, mapsize);
|
||||
return gst_buffer_create_sub (map, offset - mapbase, size);
|
||||
ret = gst_buffer_create_sub (map, offset - mapbase, size);
|
||||
|
||||
gst_buffer_unref (map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return gst_filesrc_map_region(src,offset,size);
|
||||
|
@ -431,8 +459,8 @@ gst_filesrc_get (GstPad *pad)
|
|||
{
|
||||
GstFileSrc *src;
|
||||
GstBuffer *buf = NULL, *map;
|
||||
off_t readend,readsize,mapstart,mapend;
|
||||
gboolean eof = FALSE;
|
||||
size_t readsize;
|
||||
off_t readend,mapstart,mapend;
|
||||
GstFileSrcRegion region;
|
||||
int i;
|
||||
|
||||
|
@ -440,6 +468,18 @@ gst_filesrc_get (GstPad *pad)
|
|||
src = GST_FILESRC (gst_pad_get_parent (pad));
|
||||
g_return_val_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN), NULL);
|
||||
|
||||
// check for seek
|
||||
if (src->seek_happened) {
|
||||
src->seek_happened = FALSE;
|
||||
return gst_event_new(GST_EVENT_DISCONTINUOUS);
|
||||
}
|
||||
|
||||
// check for EOF
|
||||
if (src->curoffset == src->filelen) {
|
||||
gst_element_set_state(src,GST_STATE_PAUSED);
|
||||
return gst_event_new(GST_EVENT_EOS);
|
||||
}
|
||||
|
||||
// calculate end pointers so we don't have to do so repeatedly later
|
||||
readsize = src->block_size;
|
||||
readend = src->curoffset + src->block_size; // note this is the byte *after* the read
|
||||
|
@ -450,7 +490,6 @@ gst_filesrc_get (GstPad *pad)
|
|||
if (readend > src->filelen) {
|
||||
readsize = src->filelen - src->curoffset;
|
||||
readend = src->curoffset;
|
||||
eof = TRUE;
|
||||
}
|
||||
|
||||
// if the start is past the mapstart
|
||||
|
@ -458,15 +497,15 @@ gst_filesrc_get (GstPad *pad)
|
|||
// if the end is before the mapend, the buffer is in current mmap region...
|
||||
// ('cause by definition if readend is in the buffer, so's readstart)
|
||||
if (readend <= mapend) {
|
||||
// printf("read buf %d+%d lives in current mapbuf %d+%d, creating subbuffer of mapbuf\n",
|
||||
// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
fs_print ("read buf %d+%d lives in current mapbuf %d+%d, creating subbuffer of mapbuf\n",
|
||||
src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
buf = gst_buffer_create_sub (src->mapbuf, src->curoffset - GST_BUFFER_OFFSET(src->mapbuf),
|
||||
readsize);
|
||||
|
||||
// if the start actually is within the current mmap region, map an overlap buffer
|
||||
} else if (src->curoffset < mapend) {
|
||||
// printf("read buf %d+%d starts in mapbuf %d+%d but ends outside, creating new mmap\n",
|
||||
// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
fs_print ("read buf %d+%d starts in mapbuf %d+%d but ends outside, creating new mmap\n",
|
||||
src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
}
|
||||
|
||||
|
@ -478,37 +517,39 @@ gst_filesrc_get (GstPad *pad)
|
|||
// either the read buffer overlaps the start of the mmap region
|
||||
// or the read buffer fully contains the current mmap region
|
||||
// either way, it's really not relevant, we just create a new region anyway
|
||||
// printf("read buf %d+%d starts before mapbuf %d+%d, but overlaps it\n",
|
||||
// src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
fs_print ("read buf %d+%d starts before mapbuf %d+%d, but overlaps it\n",
|
||||
src->curoffset,readsize,GST_BUFFER_OFFSET(src->mapbuf),GST_BUFFER_SIZE(src->mapbuf));
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
}
|
||||
|
||||
// then deal with the case where the read buffer is totally outside
|
||||
if (buf == NULL) {
|
||||
// first check to see if there's a map that covers the right region already
|
||||
// printf("searching for mapbuf to cover %d+%d\n",src->curoffset,readsize);
|
||||
fs_print ("searching for mapbuf to cover %d+%d\n",src->curoffset,readsize);
|
||||
region.offset = src->curoffset;
|
||||
region.size = readsize;
|
||||
map = g_tree_search(src->map_regions,gst_filesrc_search_region_match,®ion);
|
||||
map = g_tree_search (src->map_regions,
|
||||
(GCompareFunc) gst_filesrc_search_region_match,
|
||||
®ion);
|
||||
|
||||
// if we found an exact match, subbuffer it
|
||||
if (map != NULL) {
|
||||
// printf("found mapbuf at %d+%d, creating subbuffer\n",GST_BUFFER_OFFSET(map),GST_BUFFER_SIZE(map));
|
||||
fs_print ("found mapbuf at %d+%d, creating subbuffer\n",GST_BUFFER_OFFSET(map),GST_BUFFER_SIZE(map));
|
||||
buf = gst_buffer_create_sub (map, src->curoffset - GST_BUFFER_OFFSET(map), readsize);
|
||||
|
||||
// otherwise we need to create something out of thin air
|
||||
} else {
|
||||
// if the read buffer crosses a mmap region boundary, create a one-off region
|
||||
if ((src->curoffset / src->mapsize) != (readend / src->mapsize)) {
|
||||
// printf("read buf %d+%d crosses a %d-byte boundary, creating a one-off\n",
|
||||
// src->curoffset,readsize,src->mapsize);
|
||||
fs_print ("read buf %d+%d crosses a %d-byte boundary, creating a one-off\n",
|
||||
src->curoffset,readsize,src->mapsize);
|
||||
buf = gst_filesrc_map_small_region (src, src->curoffset, readsize);
|
||||
|
||||
// otherwise we will create a new mmap region and set it to the default
|
||||
} else {
|
||||
off_t nextmap = src->curoffset - (src->curoffset % src->mapsize);
|
||||
// printf("read buf %d+%d in new mapbuf at %d+%d, mapping and subbuffering\n",
|
||||
// src->curoffset,readsize,nextmap,src->mapsize);
|
||||
fs_print ("read buf %d+%d in new mapbuf at %d+%d, mapping and subbuffering\n",
|
||||
src->curoffset,readsize,nextmap,src->mapsize);
|
||||
// first, we're done with the old mapbuf
|
||||
gst_buffer_unref(src->mapbuf);
|
||||
// create a new one
|
||||
|
@ -525,8 +566,6 @@ gst_filesrc_get (GstPad *pad)
|
|||
*(GST_BUFFER_DATA(buf)+i) = *(GST_BUFFER_DATA(buf)+i);
|
||||
}
|
||||
|
||||
// if we hit EOF,
|
||||
|
||||
/* we're done, return the buffer */
|
||||
src->curoffset += GST_BUFFER_SIZE(buf);
|
||||
return buf;
|
||||
|
@ -567,6 +606,7 @@ gst_filesrc_close_file (GstFileSrc *src)
|
|||
{
|
||||
g_return_if_fail (GST_FLAG_IS_SET (src, GST_FILESRC_OPEN));
|
||||
|
||||
g_print ("close\n");
|
||||
/* close the file */
|
||||
close (src->fd);
|
||||
|
||||
|
@ -613,6 +653,7 @@ gst_filesrc_srcpad_event(GstPad *pad, GstEventType event, gint64 location, guint
|
|||
} else if (data == SEEK_END) {
|
||||
src->curoffset = src->filelen - (guint64)location;
|
||||
}
|
||||
src->seek_happened = TRUE;
|
||||
// push a discontinuous event?
|
||||
return TRUE;
|
||||
}
|
||||
|
|
452
plugins/elements/gstsinesrc.c
Normal file
452
plugins/elements/gstsinesrc.c
Normal file
|
@ -0,0 +1,452 @@
|
|||
/* 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;
|
||||
}
|
96
plugins/elements/gstsinesrc.h
Normal file
96
plugins/elements/gstsinesrc.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* 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__ */
|
|
@ -56,7 +56,7 @@ GST_PADTEMPLATE_FACTORY (tee_src_factory,
|
|||
static void gst_tee_class_init (GstTeeClass *klass);
|
||||
static void gst_tee_init (GstTee *tee);
|
||||
|
||||
static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp);
|
||||
static GstPad* gst_tee_request_new_pad (GstElement *element, GstPadTemplate *temp, const gchar *unused);
|
||||
|
||||
static void gst_tee_set_property (GObject *object, guint prop_id,
|
||||
const GValue *value, GParamSpec *pspec);
|
||||
|
@ -127,7 +127,7 @@ gst_tee_init (GstTee *tee)
|
|||
}
|
||||
|
||||
static GstPad*
|
||||
gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ)
|
||||
gst_tee_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar *unused)
|
||||
{
|
||||
gchar *name;
|
||||
GstPad *srcpad;
|
||||
|
|
|
@ -55,7 +55,9 @@ int main(int argc,char *argv[]) {
|
|||
gst_pad_connect(gst_element_get_pad(queue,"src"),
|
||||
gst_element_get_pad(play,"sink"));
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlSaveFile("ac3play.gst", gst_xml_write(GST_ELEMENT(pipeline)));
|
||||
#endif
|
||||
|
||||
// set thread start state
|
||||
g_object_set(G_OBJECT(decodethread),"create_thread",TRUE,NULL);
|
||||
|
|
|
@ -128,7 +128,9 @@ int main(int argc,char *argv[]) {
|
|||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_READY);
|
||||
gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);
|
||||
|
||||
#ifndef GST_DISABLE_LOADSAVE
|
||||
xmlSaveFile("aviparse.xml",gst_xml_write(GST_ELEMENT(pipeline)));
|
||||
#endif
|
||||
|
||||
g_print("about to enter loop\n");
|
||||
|
||||
|
|
10
test/bufspeed/.gitignore
vendored
Normal file
10
test/bufspeed/.gitignore
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
Makefile
|
||||
Makefile.in
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
.deps
|
||||
.libs
|
||||
*.xml
|
||||
test1
|
||||
test2
|
6
test/bufspeed/Makefile.am
Normal file
6
test/bufspeed/Makefile.am
Normal file
|
@ -0,0 +1,6 @@
|
|||
noinst_PROGRAMS = test1 test2
|
||||
|
||||
test1_SOURCES = test1.c gstbuffer.c gstmempool.c
|
||||
|
||||
#LIBS += $(GST_LIBS)
|
||||
CFLAGS += $(GST_CFLAGS)
|
6
test/bufspeed/README
Normal file
6
test/bufspeed/README
Normal file
|
@ -0,0 +1,6 @@
|
|||
benchmark of 5000000 gst_buffer_new/free on 0.2.1 code
|
||||
------------------------------------------------------
|
||||
gstmemchunk, no lock: real 0m1.309s user 0m1.220s sys 0m0.070s
|
||||
gmemchunk, no lock: real 0m3.872s user 0m3.740s sys 0m0.090s
|
||||
gstmemchunk, lock: real 0m5.306s user 0m5.160s sys 0m0.100s
|
||||
gmemchunk, lock: real 0m8.001s user 0m7.890s sys 0m0.080s
|
495
test/bufspeed/gstbuffer.c
Normal file
495
test/bufspeed/gstbuffer.c
Normal file
|
@ -0,0 +1,495 @@
|
|||
/* 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);
|
||||
}
|
174
test/bufspeed/gstbuffer.h
Normal file
174
test/bufspeed/gstbuffer.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
/* 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__ */
|
191
test/bufspeed/gstmempool.c
Normal file
191
test/bufspeed/gstmempool.c
Normal file
|
@ -0,0 +1,191 @@
|
|||
#include "gstmempool.h"
|
||||
|
||||
#ifdef __SMP__
|
||||
#define POOL_LOCK "lock ; "
|
||||
#else
|
||||
#define POOL_LOCK ""
|
||||
#endif
|
||||
|
||||
#define GST_MEM_POOL_AREA(pool) (((GstMemPoolElement*)(pool))->area)
|
||||
#define GST_MEM_POOL_DATA(pool) ((gpointer)(((GstMemPoolElement*)(pool)) + 1))
|
||||
#define GST_MEM_POOL_LINK(mem) ((GstMemPoolElement*)((guint8*)(mem) - sizeof (GstMemPoolElement)))
|
||||
|
||||
#define USE_ASM
|
||||
|
||||
/*******************************************************
|
||||
* area size
|
||||
* +-----------------------------------------+
|
||||
* pool size
|
||||
* +------------+
|
||||
*
|
||||
* !next!data... !next!data.... !next!data...
|
||||
* ! ^ ! ^ !
|
||||
* +-------------+ +------------+ +---> NULL
|
||||
*
|
||||
*/
|
||||
static gboolean
|
||||
populate (GstMemPool *mem_pool)
|
||||
{
|
||||
guint8 *area;
|
||||
gint i;
|
||||
|
||||
if (mem_pool->cleanup)
|
||||
return FALSE;
|
||||
|
||||
area = (guint8 *) g_malloc (mem_pool->area_size);
|
||||
|
||||
for (i=0; i < mem_pool->area_size; i += mem_pool->pool_size) {
|
||||
guint8 *areap = area + i;
|
||||
|
||||
GST_MEM_POOL_AREA (areap) = (GstMemPoolElement *)area;
|
||||
|
||||
if (mem_pool->alloc_func) {
|
||||
mem_pool->alloc_func (mem_pool, GST_MEM_POOL_DATA (areap));
|
||||
}
|
||||
|
||||
gst_mem_pool_free (mem_pool, GST_MEM_POOL_DATA (areap));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
GstMemPool*
|
||||
gst_mem_pool_new (gchar* name, gint atom_size, gulong area_size, gint type,
|
||||
GstMemPoolAllocFunc alloc_func,
|
||||
GstMemPoolFreeFunc free_func)
|
||||
{
|
||||
GstMemPool *mem_pool;
|
||||
|
||||
g_return_val_if_fail (atom_size > 0, NULL);
|
||||
g_return_val_if_fail (area_size >= atom_size, NULL);
|
||||
|
||||
mem_pool = g_malloc (sizeof (GstMemPool));
|
||||
|
||||
mem_pool->pool_size = atom_size + sizeof (GstMemPoolElement);
|
||||
area_size = (area_size/atom_size) * mem_pool->pool_size;
|
||||
|
||||
mem_pool->name = g_strdup (name);
|
||||
mem_pool->free = NULL;
|
||||
mem_pool->cnt = 0;
|
||||
mem_pool->atom_size = atom_size;
|
||||
mem_pool->area_size = area_size;
|
||||
mem_pool->cleanup = FALSE;
|
||||
mem_pool->alloc_func = alloc_func;
|
||||
mem_pool->free_func = free_func;
|
||||
mem_pool->chunk_lock = g_mutex_new ();
|
||||
|
||||
populate (mem_pool);
|
||||
|
||||
return mem_pool;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
free_area (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
g_print ("free %p\n", key);
|
||||
g_free (key);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gst_mem_pool_destroy (GstMemPool *mem_pool)
|
||||
{
|
||||
GHashTable *elements = g_hash_table_new (NULL, NULL);
|
||||
gpointer data;
|
||||
|
||||
mem_pool->cleanup = TRUE;
|
||||
|
||||
data = gst_mem_pool_alloc (mem_pool);
|
||||
while (data) {
|
||||
GstMemPoolElement *elem = GST_MEM_POOL_LINK (data);
|
||||
|
||||
g_hash_table_insert (elements, GST_MEM_POOL_AREA (elem), NULL);
|
||||
|
||||
data = gst_mem_pool_alloc (mem_pool);
|
||||
}
|
||||
g_hash_table_foreach_remove (elements, free_area, NULL);
|
||||
|
||||
g_hash_table_destroy (elements);
|
||||
g_free (mem_pool->name);
|
||||
g_free (mem_pool);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gst_mem_pool_alloc (GstMemPool *mem_pool)
|
||||
{
|
||||
GstMemPoolElement *pool = NULL;
|
||||
|
||||
g_return_val_if_fail (mem_pool != NULL, NULL);
|
||||
|
||||
again:
|
||||
#ifdef USE_ASM
|
||||
__asm__ __volatile__ (" testl %%eax, %%eax \n\t"
|
||||
" jz 20f \n"
|
||||
"10: \t"
|
||||
" movl (%%eax), %%ebx \n\t"
|
||||
" movl %%edx, %%ecx \n\t"
|
||||
" incl %%ecx \n\t"
|
||||
POOL_LOCK "cmpxchg8b %1 \n\t"
|
||||
" jz 20f \n\t"
|
||||
" testl %%eax, %%eax \n\t"
|
||||
" jnz 10b \n"
|
||||
"20:\t"
|
||||
:"=a" (pool)
|
||||
:"m" (*mem_pool), "a" (mem_pool->free), "d" (mem_pool->cnt)
|
||||
:"ecx", "ebx");
|
||||
#else
|
||||
g_mutex_lock (mem_pool->chunk_lock);
|
||||
if (mem_pool->free) {
|
||||
pool = mem_pool->free;
|
||||
mem_pool->free = pool->link;
|
||||
}
|
||||
g_mutex_unlock (mem_pool->chunk_lock);
|
||||
#endif
|
||||
|
||||
if (!pool) {
|
||||
//g_print ("extending\n");
|
||||
if (populate (mem_pool))
|
||||
goto again;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
return GST_MEM_POOL_DATA (pool);
|
||||
}
|
||||
|
||||
gpointer
|
||||
gst_mem_pool_alloc0 (GstMemPool *mem_pool)
|
||||
{
|
||||
gpointer mem = gst_mem_pool_alloc (mem_pool);
|
||||
|
||||
if (mem)
|
||||
memset (mem, 0, mem_pool->atom_size);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void
|
||||
gst_mem_pool_free (GstMemPool *mem_pool, gpointer mem)
|
||||
{
|
||||
GstMemPoolElement *pool;
|
||||
|
||||
g_return_if_fail (mem_pool != NULL);
|
||||
g_return_if_fail (mem != NULL);
|
||||
|
||||
pool = GST_MEM_POOL_LINK (mem);
|
||||
|
||||
#ifdef USE_ASM
|
||||
__asm__ __volatile__ ( "1: \t"
|
||||
" movl %2, (%1) \n"
|
||||
POOL_LOCK "cmpxchg %1, %0 \n\t"
|
||||
" jnz 1b \n\t"
|
||||
:
|
||||
:"m" (*mem_pool), "r" (pool), "a" (mem_pool->free));
|
||||
#else
|
||||
g_mutex_lock (mem_pool->chunk_lock);
|
||||
pool->link = mem_pool->free;
|
||||
mem_pool->free = pool;
|
||||
g_mutex_unlock (mem_pool->chunk_lock);
|
||||
#endif
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue